47

Я нашел что-то в сценарии, но не принадлежал к основному сценарию. Там было :> в строке.

Не могли бы вы объяснить мне, что это значит?

:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile

3 ответа3

46

Там было:> в строке bash-скрипта. Что это значит?

:> file

Это краткий способ сказать:

  • Если file не существует, создайте его, иначе обрежьте его до 0 байтов.

Это означает, что вы можете быть уверены, что file существует и он пуст.

Вы также можете использовать > file но :> file является более переносимым.

См. Вопрос переполнения стека. Какова цель GNU Bash Builtin? для дополнительной информации.

29

Это похоже на причудливый способ создания нового файла. В bash : пустая команда:

$ type : 
: is a shell builtin 
$ help : 
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.

> перенаправляет вывод : в файл.

11

: другое имя для 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 содержит некоторые полезные сведения о сценариях, которые не сломаются, независимо от того, какие данные или имена файлов вы добавляете в сценарий.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .