Co ważne, :>nie jest to pojedynczy operator. Łatwiej zrozumieć, jeśli : > filezamiast tego czytasz .
jpfx1342,
Oznacza to, że osoba, pisząc scenariusz powinien przekierowany wyjście z pętli do pliku: while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file. Lub jeszcze lepiej, powinni byli użyć odpowiedniego narzędzia do pracy, awk, jak sugeruje Peter . Nawiasem mówiąc, prawie zawsze chcesz używać -rprzełącznika zread .
Tom Fenech
Poza uderzeniem byłaby to buźka dla wrony.
smci
Odpowiedzi:
46
Było:> w wierszu skryptu bash. Co to znaczy?
:> file
Jest to skrótowy sposób powiedzenia:
Jeśli filenie istnieje, utwórz go, skróć go do 0bajtów.
Oznacza to, że możesz być pewien, że fileistnieje i jest pusty.
Możesz także użyć, > fileale :> filejest bardziej przenośny.
Nie rozumiem drugiej linii. Myślałem, że czytają zmienne. Echo poleceń jest również dziwne. Czy możesz wytłumaczyć?
diego9403,
Nie jestem ekspertem, ale myślę, Unix druga linia czyta rzeczy z otherfilei echoy im się file. Dokonuje również zmiennych na podstawie tego, co czyta ... Jeśli chcesz uzyskać jednoznaczną odpowiedź, zadaj własne pytanie.
DavidPostill
2
@ diego9403: readpobiera dane wejściowe ze standardowego wejścia. Samodzielnie czytałby to, co piszesz. Ponieważ stdin zostało przekierowane, <otherfilezawartość otherfile„jest wpisywana” na stdin. Więc readprzenosi wartości linia po linii do zmiennych $ A, $ B, $ C, $ D i $ E.
slebetman
Czyli jest to bardziej niejasna alternatywa dla truncateCoreutils?
Federico Poloni,
1
@PeterCordes Nie miałem na myśli „niejasnego”, jak w „rzadkościach”, ale jak w „mniej czytelnych dla czytelnika”.
Federico Poloni,
29
Wygląda na fantazyjny sposób tworzenia nowego pliku. In bash:jest poleceniem zerowym:
$ type :: is a shell builtin
$ help ::::Null command.No effect; the command does nothing.ExitStatus:Always succeeds.
:jest skrótem od true. Możliwe, że w niektórych powłokach truenie jest wbudowany? Oba są wbudowane w bash.
Peter Cordes,
12
:to inna nazwa dla true. Oba są wbudowanymi powłokami w bash, ale nie ma /bin/:, tylko /bin/true. Przekierowanie danych wyjściowych powoduje powłokę do open(2)pliku za pomocą O_CREAT|O_TRUNC. Jeśli nic nie jest zapisane, pozostaje na zerowej długości.
Złożenie tych dwóch części razem :> filejest dość powszechnym idiomem obcinania plików. Większość ludzi starałaby się jednak robić mniej dziwnie, pisząc : >file.
Ponieważ zapytałeś w komentarzu do drugiej linii, zamienię moje komentarze w odpowiedź. (mimo że nie zadałeś tego w swoim pytaniu).
Drugi wiersz to pętla, która odczytuje wiersze z otherfileniektórych nazwanych zmiennych. Ciało pętli używa echodo drukowania ich za pomocą ;separatorów zamiast jakichkolwiek białych znaków, które mieli wcześniej. filejest zamykany i ponownie otwierany (w celu dołączenia) każdej iteracji, ponieważ przekierowanie znajduje się w pętli. Używanie while ...;do read -r ...;done <otherfile >filezmniejszyłoby ssanie i uniknęło konieczności obcięcia pliku w pierwszej kolejności. read -rnie je \jako postać ucieczki.
Przetwarzanie tekstu w bash jest dość powolne. Część tego jest nieunikniona: readmusi przejść jeden bajt na raz (jedno read(2)wywołanie systemowe na bajt), aby uniknąć przekroczenia końca linii. Lepiej byłoby użyć odpowiedniego narzędzia do pracy:
--oznacza, że twój skrypt się nie psuje, jeśli otherfilenazywa się coś głupiego jak --version.
Ustawienie Separatora pól wyjściowych ;oznacza, że możesz po prostu przekazać wiele pól jako argumenty do wydrukowania. Shell readprzypisuje całą resztę linii spacją do ostatniej zmiennej, ale nie ma sposobu, aby powiedzieć awk, aby dzielił się tylko na 5. Jeśli to ważne, być może po prostu używaj pętli bash, ponieważ jest to niewygodne w awk. Perl sprawia, że jest to łatwe, ponieważ splitmoże przyjmować argument max-field arg, ale jego uruchomienie jest znacznie wolniejsze niż awk.
W rzeczywistości okazało się, że nie jest to takie trudne, tylko brzydkie wyrażenie regularne do napisania. Aby uzyskać resztę linii zamiast $5w awk, zapętlanie pól wciąż traci pierwotne białe znaki. Moim pierwszym praktycznym pomysłem jest użycie gensubna $0(całej linii), aby usunąć pierwsze 4 pola (tj. Spacja, po której następuje spacja), pozostawiając wszystko inne:
Zrobiłem to poprawnie przy pierwszej próbie, ale fakt, że byłem pod wrażeniem samego siebie, mówi coś o czytelności tego kodu awk. >. <
Zwróć uwagę, jak to jest tak samo printjak poprzednio, ale z tailzamiast $5.
echo 'A B c DD e f g f'|
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Byłoby to bardziej imponujące, gdybym mógł skopiować / wkleić literał i pokazać, że przyszedł w wyniku. Wpisz jeden w bash za pomocą ^ Q. ctrl-Q oznacza Cytuj kolejne naciśnięcie klawisza jako dosłowny znak, ponieważ edycja linii w stylu emacsa basha jest w tym przypadku taka sama, jak faktyczna emacs.
http://mywiki.wooledge.org/BashFAQ zawiera przydatne informacje na temat skryptów w sposób, który nie ulegnie uszkodzeniu bez względu na to, jakie dane lub nazwy plików rzucasz na skrypt.
:>
nie jest to pojedynczy operator. Łatwiej zrozumieć, jeśli: > file
zamiast tego czytasz .while read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file
. Lub jeszcze lepiej, powinni byli użyć odpowiedniego narzędzia do pracy, awk, jak sugeruje Peter . Nawiasem mówiąc, prawie zawsze chcesz używać-r
przełącznika zread
.Odpowiedzi:
Było:> w wierszu skryptu bash. Co to znaczy?
Jest to skrótowy sposób powiedzenia:
file
nie istnieje, utwórz go, skróć go do0
bajtów.Oznacza to, że możesz być pewien, że
file
istnieje i jest pusty.Możesz także użyć,
> file
ale:> file
jest bardziej przenośny.Zobacz pytanie Przepełnienie stosu Jaki jest cel wbudowanego GNU Bash „:” (dwukropka)? po więcej informacji.
źródło
otherfile
iecho
y im sięfile
. Dokonuje również zmiennych na podstawie tego, co czyta ... Jeśli chcesz uzyskać jednoznaczną odpowiedź, zadaj własne pytanie.read
pobiera dane wejściowe ze standardowego wejścia. Samodzielnie czytałby to, co piszesz. Ponieważ stdin zostało przekierowane,<otherfile
zawartośćotherfile
„jest wpisywana” na stdin. Więcread
przenosi wartości linia po linii do zmiennych $ A, $ B, $ C, $ D i $ E.truncate
Coreutils?Wygląda na fantazyjny sposób tworzenia nowego pliku. In
bash
:
jest poleceniem zerowym:>
przekierowuje wyjście:
do pliku.źródło
>
robi:
jest skrótem odtrue
. Możliwe, że w niektórych powłokachtrue
nie jest wbudowany? Oba są wbudowane w bash.:
to inna nazwa dlatrue
. Oba są wbudowanymi powłokami w bash, ale nie ma/bin/:
, tylko/bin/true
. Przekierowanie danych wyjściowych powoduje powłokę doopen(2)
pliku za pomocąO_CREAT|O_TRUNC
. Jeśli nic nie jest zapisane, pozostaje na zerowej długości.Złożenie tych dwóch części razem
:> file
jest dość powszechnym idiomem obcinania plików. Większość ludzi starałaby się jednak robić mniej dziwnie, pisząc: >file
.Ponieważ zapytałeś w komentarzu do drugiej linii, zamienię moje komentarze w odpowiedź. (mimo że nie zadałeś tego w swoim pytaniu).
Drugi wiersz to pętla, która odczytuje wiersze z
otherfile
niektórych nazwanych zmiennych. Ciało pętli używaecho
do drukowania ich za pomocą;
separatorów zamiast jakichkolwiek białych znaków, które mieli wcześniej.file
jest zamykany i ponownie otwierany (w celu dołączenia) każdej iteracji, ponieważ przekierowanie znajduje się w pętli. Używaniewhile ...;do read -r ...;done <otherfile >file
zmniejszyłoby ssanie i uniknęło konieczności obcięcia pliku w pierwszej kolejności.read -r
nie je\
jako postać ucieczki.Przetwarzanie tekstu w bash jest dość powolne. Część tego jest nieunikniona:
read
musi przejść jeden bajt na raz (jednoread(2)
wywołanie systemowe na bajt), aby uniknąć przekroczenia końca linii. Lepiej byłoby użyć odpowiedniego narzędzia do pracy:--
oznacza, że twój skrypt się nie psuje, jeśliotherfile
nazywa się coś głupiego jak--version
.Ustawienie Separatora pól wyjściowych
;
oznacza, że możesz po prostu przekazać wiele pól jako argumenty do wydrukowania. Shellread
przypisuje całą resztę linii spacją do ostatniej zmiennej, ale nie ma sposobu, aby powiedzieć awk, aby dzielił się tylko na 5. Jeśli to ważne, być może po prostu używaj pętli bash, ponieważ jest to niewygodne w awk. Perl sprawia, że jest to łatwe, ponieważsplit
może przyjmować argument max-field arg, ale jego uruchomienie jest znacznie wolniejsze niż awk.W rzeczywistości okazało się, że nie jest to takie trudne, tylko brzydkie wyrażenie regularne do napisania. Aby uzyskać resztę linii zamiast
$5
w awk, zapętlanie pól wciąż traci pierwotne białe znaki. Moim pierwszym praktycznym pomysłem jest użyciegensub
na$0
(całej linii), aby usunąć pierwsze 4 pola (tj. Spacja, po której następuje spacja), pozostawiając wszystko inne:Zrobiłem to poprawnie przy pierwszej próbie, ale fakt, że byłem pod wrażeniem samego siebie, mówi coś o czytelności tego kodu awk. >. <
Zwróć uwagę, jak to jest tak samo
print
jak poprzednio, ale ztail
zamiast$5
.Byłoby to bardziej imponujące, gdybym mógł skopiować / wkleić literał i pokazać, że przyszedł w wyniku. Wpisz jeden w bash za pomocą ^ Q. ctrl-Q oznacza Cytuj kolejne naciśnięcie klawisza jako dosłowny znak, ponieważ edycja linii w stylu emacsa basha jest w tym przypadku taka sama, jak faktyczna emacs.
http://mywiki.wooledge.org/BashFAQ zawiera przydatne informacje na temat skryptów w sposób, który nie ulegnie uszkodzeniu bez względu na to, jakie dane lub nazwy plików rzucasz na skrypt.
źródło