Mam następujące dane (listę pakietów R przeanalizowanych z pliku Rmarkdown), które chcę przekształcić w listę, którą mogę przekazać do R, aby zainstalować:
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
Chcę przekształcić listę w listę formularza:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
Obecnie mam potok bash, który przechodzi z surowego pliku na powyższą listę:
grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')' \
| sort | uniq
Chcę dodać krok, aby przekształcić nowe wiersze w listę rozdzielaną przecinkami. Próbowałem dodać tr '\n' '","'
, co się nie udaje. Próbowałem również kilka następujących odpowiedzi Przepełnienie stosu, które również nie powiodły się:
W library(stringr)))phics)
rezultacie powstaje .
W ,%
rezultacie powstaje .
Ta odpowiedź (z -i
usuniętą flagą) tworzy dane wyjściowe identyczne z danymi wejściowymi.
'
albo"
.Odpowiedzi:
Możesz dodawać cudzysłowy za pomocą sed, a następnie scalać wiersze za pomocą wklejania :
Jeśli korzystasz z systemu opartego na jądrach GNU (tj. Linux), możesz pominąć końcowe
'-'
.Jeśli dane wejściowe mają zakończenia linii w stylu DOS (jak sugeruje @phk), możesz zmodyfikować polecenie w następujący sposób:
źródło
sed 's/^\|$/"/g'|paste -sd, -
sed
sam:sed 's/.*/"&"/;:l;N;s/\n\(.*\)$/, "\1"/;tl'
paste
osobno;)awk
: Alternatywa z mniejszą ilością ucieczek powłoki, a zatem bardziej czytelna: Wynik: Wyjaśnienie:Sam
Uwagaawk
skrypt bez ucieczki jestBEGIN { ORS="" } { print p"'"$0"'"; p=", " } END { print "\n" }
. Po wydrukowaniu pierwszego wpisu zmiennap
jest ustawiana (wcześniej jest jak pusty ciąg). Dzięki tej zmiennejp
każdy wpis (lub in-awk
mów: rekord ) jest poprzedzany i dodatkowo drukowany z pojedynczymi cudzysłowami wokół niego.awk
Zmienna separator rekordów wyjściowychORS
nie jest potrzebne (od prefiks robi to za Ciebie), więc jest on ustawiony na pusty wBEGIN
ING. Aha i możemy nasz plikEND
z nową linią (np. Dzięki czemu działa z dalszymi narzędziami do przetwarzania tekstu); jeśli nie będzie to potrzebne, część zEND
i wszystko po nim (wewnątrz pojedynczych cudzysłowów) można usunąć.Jeśli masz zakończenia linii w stylu Windows / DOS (
\r\n
), musisz je\n
najpierw przekonwertować na styl UNIX ( ). Aby to zrobić, możesz umieścićtr -d '\015'
na początku swojego potoku:(Zakładając, że
\r
w twoim pliku nie ma zastosowania dla s. Bardzo bezpieczne założenie tutaj.)Alternatywnie, wystarczy
dos2unix /path/to/input.list
raz uruchomić, aby przekonwertować plik w miejscu.źródło
', 'stringr23aphics
jako wynik.print p"'"'"'"$0"'"'"'"; p=", "
—Holy cytaty, Batman!p"'\''"$0"'\''";
też by działał (choć nie jest POSIXY), lub alternatywnie użyciebash
ciągów cytowania C ($''
) nawet po prostuprint p"\'"$0"\'";
( choć może wymagać podwojenia innych odwrotnych ukośników), ale jest już inna metoda wykorzystującaawk
znaki ucieczki.Jak pokazuje połączona odpowiedź @ don_crissti , opcja wklejania graniczy z niewiarygodnie szybkim - potokowanie jądra Linuksa jest wydajniejsze, niż bym się spodziewał, gdybym go nie wypróbował. Co ciekawe, jeśli możesz być zadowolony z pojedynczego przecinka oddzielającego elementy listy zamiast przecinka + spacji, wklej potok
jest szybszy niż nawet rozsądny
flex
program (!)Ale jeśli tylko przyzwoita wydajność jest do zaakceptowania (a jeśli nie przeprowadzasz testu warunków skrajnych, nie będziesz w stanie zmierzyć różnic o stałym współczynniku, wszystkie są natychmiastowe) i chcesz zarówno elastyczności z separatorami, jak i rozsądnej -liner-y-ness,
jest twoim biletem. Tak, wygląda to na szum linii, ale
H;1h;$!d;x
idiom jest właściwym sposobem, aby wszystko zepsuć, gdy tylko zauważysz, że cała rzecz jest naprawdę łatwa do odczytania, po niejs/.*/'&'/
następuje slurp i as/\n/, /g
.edycja: granicząc z absurdem, dość łatwo jest wygrać, aby pokonać wszystko inne puste, po prostu powiedz stdio, że nie potrzebujesz wbudowanej synchronizacji wielowątkowości / obsługi sygnału:
i pod wpływem stresu jest 2-3 razy szybszy niż rurociągi wklejane, które same są co najmniej 5 razy szybsze niż wszystko inne.
źródło
(paste -d\ \'\' /dev/null /dev/null - /dev/null | paste -sd, -) <infile | cut -c2-
zrobiłby przecinek + spację @ prawie tak samo szybko, jak zauważyłeś, nie jest to tak naprawdę elastyczne, jeśli potrzebujesz jakiegoś fantazyjnego ciągu jako separatoraflex
rzeczy są cholernie fajne, stary ... po raz pierwszy widzę, jak ktoś publikujeflex
kod na tej stronie ... duża opinia! Proszę zamieścić więcej takich rzeczy.Perl
Python one-liner:
Działa w prosty sposób - przekierowujemy input.txt na stdin za pomocą
<
operatora powłoki , odczytujemy każdy wiersz na liście,.strip()
usuwając znaki nowego wiersza irepr()
tworząc cytowaną reprezentację każdego wiersza. Lista jest następnie łączona w jeden duży ciąg za pomocą.join()
funkcji, z,
separatoremAlternatywnie możemy użyć
+
do połączenia cytatów z każdą linią pozbawioną linii.Perl
Zasadniczo taki sam pomysł jak poprzednio: odczytaj wszystkie wiersze, usuń znak nowej linii, umieść w pojedynczych cudzysłowach, umieść wszystko w tablicy @cvs i wydrukuj wartości tablic połączone przecinkami.
„d3heatmap”, „data.table”, „ggplot2”, „htmltools”, „htmlwidgets”, „metricsgraphics”, „networkD3”, „plotly”, „reshape2”, „scales”, „stringr”
źródło
join
powinny mieć możliwość wykonania iteratora, dlatego nie powinno być potrzeby materializowania pętli stdin do listyMyślę, że poniższe czynności powinny wystarczyć, zakładając, że dane znajdują się w tekście pliku
Użyjmy tablic, które mają podstawienie na zimno:
Dane wyjściowe skryptu powinny wyglądać następująco:
Wierzę, że tego właśnie szukałeś?
źródło
bash
i chociaż można bezpiecznie założyć, że ktoś może go użyć (w końcu AFAIK jest najczęściej używaną powłoką), nadal nie należy go uważać za pewnik. Są też części, w których możesz lepiej pracować przy cytowaniu (wstawianie podwójnych cudzysłowów). Na przykład, chociaż w nazwach pakietów raczej nie ma spacji, nadal dobrze jest cytować zmienne, a nie, możesz uruchomić na nim shellcheck.net i zobaczyć tam uwagi i objaśnienia.Często mam bardzo podobny scenariusz: kopiuję kolumnę z Excela i chcę przekonwertować zawartość na listę oddzieloną przecinkami (do późniejszego użycia w zapytaniu SQL, takim jak
... WHERE col_name IN <comma-separated-list-here>
).Oto, co mam w moim .bashrc:
Następnie uruchamiam
lbl
(„linia po linii”) na linii cmd, która czeka na dane wejściowe, wklejam zawartość ze schowka, naciśnij,<C-D>
a funkcja zwraca dane otoczone()
. Wygląda to tak:(Nie pamiętam, dlaczego umieściłem tutaj dos2unix, prawdopodobnie dlatego, że często powoduje to problemy w konfiguracji mojej firmy).
źródło
Niektóre wersje sed działają nieco inaczej, ale na moim Macu mogę obsłużyć wszystko oprócz „uniq” w sed:
Niestety, aby naprawić unikalną część, musisz zrobić coś takiego:
--Paweł
źródło
Zabawne, że aby użyć listy tekstowej R do zainstalowania ich w R, nikt nie zaproponował rozwiązania wykorzystującego tę listę bezpośrednio w R, ale walcz z bash, perl, python, awk, sed lub czymkolwiek innym, aby wstawić cudzysłowy i przecinki w lista. Nie jest to wcale konieczne, a ponadto nie rozwiązuje problemu wprowadzania i używania przekształconej listy w języku R.
Możesz po prostu załadować zwykły plik tekstowy (wspomniany
packages.txt
) jako ramkę danych z pojedynczą zmienną, którą możesz wyodrębnić jako wektor, bezpośrednio przezinstall.packages
. Tak więc przekonwertuj go na przydatny obiekt R i zainstaluj tę listę:Lub bez zewnętrznego pliku:
źródło