:
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 :> 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żywa echo
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żywanie while ...;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 (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 otherfile
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. Shell read
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życie gensub
na $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 print
jak poprzednio, ale z tail
zamiast $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 .