$(<file)(також працює з `<file`) - це спеціальний оператор оболонки Korn, скопійований zshі bash. Це дуже схоже на заміну команд, але насправді це не так.
У оболонках POSIX проста команда:
< file var1=value1 > file2 cmd 2> file3 args 3> file4
Усі частини необов’язкові, ви можете мати лише перенаправлення, лише команди, лише призначення або комбінації.
Якщо є перенаправлення, але немає команди, перенаправлення виконуються (таким чином, а > fileвідкриваються і врізаються file), але тоді нічого не відбувається. Тому
< file
Відкривається fileдля читання, але потім нічого не відбувається, оскільки немає команди. Тож fileзакрито, і все. Якби $(< file)була проста заміна команд , то вона розширилася б ні до чого.
У специфікації POSIX в $(script), якщо він scriptскладається лише з перенаправлень, що дає неозначені результати . Це дозволяє дозволити особливу поведінку оболонки Корна.
У ksh (тут перевірено ksh93u+), якщо скрипт складається з однієї і лише однієї простої команди (хоча коментарі дозволені до і після), яка складається лише з перенаправлень (без команди, без призначення) і якщо перше перенаправлення - stdin (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})або $(<file$((++n))))
- помилки читання (хоча це не помилки під час відкриття файлів або копіювання дескрипторів файлів) мовчки ігноруються.
У zshцей же самий , за винятком того , що особлива поведінка спрацьовує тільки , коли є тільки один вхід Перенаправлення файл ( <fileабо 0< file, немає <&3, <<<here, < a < b...)
Однак, за винятком емуляції інших оболонок, у:
< file
<&3
<<< here...
тобто коли є лише переадресації на вхід без команд, за межами заміни команд, zshзапускається $READNULLCMD(пейджер за замовчуванням), а коли є і вхідні, і вихідні перенаправлення, $NULLCMD( catза замовчуванням), так що навіть якщо $(<&3)його не визнано спеціальним Оператор, він все ще буде працювати як у, kshхоча, викликаючи пейджер для цього (цей пейджер діє так, catяк його stdout буде трубою).
Однак, хоч ksh's $(< 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призначення втрачається згодом).
В bash, IFS= read -rd '' var < file (також працює в zsh) є більш ефективним способом зчитування вмісту текстового файлу в змінну. Це також має перевагу збереження останніх символів нового рядка. Дивіться також $mapfile[file]в zsh(у zsh/mapfileмодулі та лише для звичайних файлів), який також працює з бінарними файлами.
Зауважимо, що варіанти на основі pdksh kshмають кілька варіацій порівняно з ksh93. Цікаво, що в mksh(одній із цих оболонок, отриманих пдкш), в
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
оптимізовано тим, що вміст документа тут (без знаків, що відкладаються) розширюється без використання тимчасового файлу або труби, як це в іншому випадку стосується тут документів, що робить його ефективним синтаксисом багаторядкового цитування.
Для того, щоб бути портативними для всіх версій ksh, zshі bash, найкраще обмежитися тільки $(<file)уникати коментарів і беручи до уваги , що зміни змінних зроблені в межах можуть або не можуть бути збережені.
bashбуде інтерпретувати це якcat filename", ви маєте на увазі, що така поведінка специфічна для заміни команд? Тому що, якщо я біжу< filenameсама, баш це не виганяє. Він нічого не виведе і поверне мене до підказки.