Я нашел что-то в сценарии, но не принадлежал к основному сценарию. Там было :>
в строке.
Не могли бы вы объяснить мне, что это значит?
:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile
Я нашел что-то в сценарии, но не принадлежал к основному сценарию. Там было :>
в строке.
Не могли бы вы объяснить мне, что это значит?
:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile
:> file
Это краткий способ сказать:
file
не существует, создайте его, иначе обрежьте его до 0
байтов.Это означает, что вы можете быть уверены, что file
существует и он пуст.
Вы также можете использовать > file
но :> file
является более переносимым.
См. Вопрос переполнения стека. Какова цель GNU Bash Builtin? для дополнительной информации.
Это похоже на причудливый способ создания нового файла. В bash
:
пустая команда:
$ type :
: is a shell builtin
$ help :
:: :
Null command.
No effect; the command does nothing.
Exit Status:
Always succeeds.
>
перенаправляет вывод :
в файл.
:
другое имя для true
. Оба являются встроенными в bash, но нет /bin/:
только a /bin/true
. Перенаправление вывода заставляет оболочку open(2)
файл с помощью O_CREAT|O_TRUNC
. Если ничего не написано, оно остается на нулевой длине.
Собрав воедино эти две части, :> file
- довольно распространенная идиома для усечения файлов. Большинство людей пытаются сделать его менее странным, написав : >file
.
Поскольку вы спросили в комментарии о второй строке, я превращу свои комментарии в ответ. (даже если вы не задавали это в своем вопросе.)
Вторая строка представляет собой цикл, который читает строки из otherfile
в некоторые именованные переменные. Тело цикла использует echo
для их печати ;
разделители вместо пробелов, которые у них были раньше. file
закрывается и повторно открывается (для добавления) каждую итерацию, потому что перенаправление находится внутри цикла. Использование while ...;do read -r ...;done <otherfile >file
будет меньше отстой и избавит от необходимости сначала обрезать файл. read -r
не ест \
как escape-символ.
Обработка текста в 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.
На самом деле, оказалось, что это не так сложно, просто уродливое выражение для написания. Чтобы получить остальную часть строки вместо $5
в awk, цикл по полям все еще теряет свой первоначальный пробел. Моя первая жизнеспособная идея - использовать 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 содержит некоторые полезные сведения о сценариях, которые не сломаются, независимо от того, какие данные или имена файлов вы добавляете в сценарий.