сценарий bash с командой grep not

$((также работает с`)— это специальный оператор оболочки Корна, скопированный zshи bash. Это очень похоже на подстановку команд, но на самом деле это не так.

В оболочках POSIX простая команда:

< file var1=value1 > file2 cmd 2> file3 args 3> file4

Все части являются необязательными, у вас могут быть только перенаправления, только команды, только назначения или комбинации.

Если есть перенаправления, но нет команды, перенаправления выполняются (, поэтому > fileоткрывается и усекается file), но тогда ничего не происходит. Так

< file

Открывает fileдля чтения, но дальше ничего не происходит, так как нет команды. Итак, fileзакрывается и все. Если бы $(< file)была простой подстановкой команды , то она не расширилась бы до нуля.

В спецификации POSIX , в $(script), если scriptсостоит только из перенаправлений, то приводит к неопределенным результатам . Это сделано для того, чтобы обеспечить особое поведение оболочки Korn.

В ksh (здесь протестировано с ksh93u+), если скрипт состоит из одной и только одной простой команды(хотя до и после разрешены комментарии до и после ), которые состоят только из перенаправлений (нет команды, нет назначения )и если первое перенаправление является стандартным вводом (fd 0 )только ввод (<, <<или<<<)перенаправление,так:

  • $(< file)
  • $(0< file)
  • $(<&3)(также $(0>&3)на самом деле, поскольку это один и тот же оператор)
  • $(< file > foo 2> $(whatever))

, но не:

  • $(> foo < file)
  • или$(0<> file)
  • или$(< file; sleep 1)
  • или$(< file; < file2)

, затем

  • все перенаправления, кроме первого, игнорируются (они анализируются)
  • и расширяется до содержимого файла/heredoc/herestring (или того, что можно прочитать из дескриптора файла при использовании таких вещей, как<&3)минус завершающие символы новой строки.

как при использовании $(cat < file), за исключением того, что

  • чтение выполняется внутри оболочки, а неcat
  • не используется ни труба, ни дополнительный процесс
  • как следствие вышеизложенного, поскольку код внутри не запускается в подоболочке, любые модификации остаются после этого (как в $(<${file=foo.txt})или$()
  • ошибки чтения (, хотя и не ошибки при открытии файлов или дублировании файловых дескрипторов ), молча игнорируются.

В zshто же самое, за исключением того, что это особое поведение запускается только при наличии только одного перенаправления ввода файла(или 0< file, нет <&3, <<, < a < b...)

Однако, за исключением случаев эмуляции других оболочек, в:

< file
<&3
<<< here...

то есть, когда есть только перенаправления ввода без команд, вне подстановки команд, zshзапускает$READNULLCMD(пейджер по умолчанию ), а когда есть перенаправления ввода и вывода,$NULLCMD(catпо умолчанию ), поэтому, даже если $(<&3)не распознан как этот специальный оператор, он все равно будет работать, как в ksh, хотя при вызове пейджера для этого (этот пейджер действует как cat, поскольку его стандартный вывод будет быть трубой ).

Однако в то время как ksh$(< a < b)расширяется до содержимого a, в zshоно расширяется до содержимого aиb(или просто b, если multiosопция отключена ),$(< a > b)скопирует aв bи ничего не расширит и т. д.

bashимеет аналогичный оператор, но с некоторыми отличиями:

  • комментарии разрешены до, но не после:

      echo "$(
         # getting the content of file
         < file)"
    

работает, но:

    echo "$(< file
       # getting the content of file
    )"

расширяется до нуля.

  • как и в zsh, только одно перенаправление файла stdin, хотя возврата к $READNULLCMDнет, поэтому $(<&3), $(< a < b)выполняют перенаправления, но не расширяются.
  • по какой-то причине, хотя bashне вызывает cat, он все же разветвляет процесс, который передает содержимое файла через канал, что делает его гораздо менее оптимизированным, чем в других оболочках. По сути, это похоже на $(cat < file), где catбудет встроенным cat.
  • как следствие вышеизложенного, любые изменения, сделанные внутри, впоследствии теряются (в $(<${file=foo.txt}), упомянутом выше, например, что $fileназначение теряется впоследствии ).

В bashIFS= read -rd '' var < file(также работает вzsh)— это более эффективный способ чтения содержимого текстового файла в переменную. Это также имеет преимущество сохранения завершающих символов новой строки. См. также $mapfile[file]вzsh(в модуле zsh/mapfileи только для обычных файлов ), который также работает с двоичными файлами.

Обратите внимание, что варианты kshна основе pdksh -имеют несколько вариаций по сравнению с ksh93. Интересно, что вmksh(одна из тех оболочек, производных от pdksh -), в

var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)

оптимизирован в том смысле, что содержимое документа (без завершающих символов новой строки )расширяется без использования временного файла или канала, как в противном случае в случае документов здесь, что делает его эффективным мульти -синтаксис цитирования строк.

Для переноса на все версии ksh, zshи bash,лучше всего ограничиться только тем, $(избегая комментариев и помня о том, что модификации переменных, сделанные внутри, могут сохраняться, а могут и не сохраняться.

0
27.05.2019, 12:00
1 ответ

Вы установили IFS только для новой строки и возврата. Таким образом, $s3lsпосле расширения и разбиения на слова будет считаться aws s3 ls --human-readable --summarize s3://ssyssplunk/ --recursiveодним словом. Bash пытается выполнить это единственное слово как команду вместо выполнения awsс набором аргументов.

Вам действительно не следует хранить команды в переменных. Вместо этого используйте массивы:

s3ls=(aws s3 ls --human-readable --summarize 's3://ssyssplunk/' --recursive)
#...
totalSize=$("${s3ls[@]}" |...)
0
28.01.2020, 03:39

Теги

Похожие вопросы