: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:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--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:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
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: > filezamiast tego czytasz .