:это другое имя для true. Оба встроены в bash, но нет /bin/:, только a /bin/true. Перенаправление вывода вызывает оболочку open(2)в файл с помощью O_CREAT|O_TRUNC. Если ничего не написано, оно остается на нулевой длине.
Соединение этих двух частей :> file- довольно распространенная идиома для усечения файлов. : >fileТем не менее, большинство людей пытались бы сделать это менее странным, когда писали .
Поскольку вы спросили в комментарии о 2-й строке, я превращу свои комментарии в ответ. (даже если вы не задавали это в своем вопросе.)
2-я строка - это цикл, который читает строки otherfileв некоторые именованные переменные. Тело цикла использует echoдля печати их с ;разделителями вместо того, что было раньше. fileзакрывается и повторно открывается (для добавления) каждую итерацию, потому что перенаправление находится внутри цикла. Использование while ...;do read -r ...;done <otherfile >fileбудет меньше отстой, и избежать необходимости сначала обрезать файл. read -rне ест \как побег
Обработка текста в bash довольно медленная. Частично это неизбежно: readприходится идти по одному байту за раз (один read(2)системный вызов на байт), чтобы избежать превышения конца строки. Было бы лучше использовать правильный инструмент для работы:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--означает, что ваш скрипт не ломается, если otherfileназван как-то глупо, как --version.
Установка разделителя поля вывода на ;означает, что вы можете просто передать несколько полей в качестве аргументов для печати. Оболочка readприсваивает последнюю переменную всей оставшейся части строки с пробелами, но нет способа сказать, чтобы awk делился только на 5. Если это важно, возможно, просто продолжайте использовать цикл bash, потому что это неудобно в awk. Perl делает это легко, поскольку он splitможет принимать аргументы max-fields, но запускать его намного медленнее, чем awk.
На самом деле, оказалось, что это не так сложно, просто уродливое выражение для написания. Для того, чтобы получить «остальную часть строки» вместо $5awk, цикл по полям все еще теряет свой первоначальный пробел. Моя первая жизнеспособная идея заключается в том, чтобы использовать gensubна $0(всю линии) , чтобы удалить первое 4 поля (т.е. не пространство с последующим пробелом), оставляя все остальное:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
Я понял это правильно с первой попытки, но тот факт, что я был впечатлен этим, говорит о читабельности этого awk-кода. >. <
Обратите внимание, что это так же, printкак и раньше, но с tailвместо $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
Это было бы более впечатляюще, если бы я мог скопировать / вставить литерал и показать, что он прошел через вывод. Введите один в bash с помощью ^ Q. ctrl-Q означает заключить в кавычки следующее нажатие клавиши как буквальный символ, так как редактирование строки в стиле bash в emacs такое же, как и в действительности emacs.
http://mywiki.wooledge.org/BashFAQ содержит некоторые полезные сведения о сценариях, которые не сломаются, независимо от того, какие данные или имена файлов вы добавляете в сценарий.
:>не один оператор. Это может быть легче понять, если вы прочитаете это как: > fileвместо этого.