Чому функція `sort <(ls -l)` працює, але `sort <(ls -l)` не працює?


32

Сьогодні я дізнаюся щось про фіфо з цією статтею: Вступ до названих труб , в якій згадується cat <(ls -l).

Я зробив кілька експериментів, використовуючи sort < (ls -l), що з'являється помилка:

-bash: syntax error near unexpected token `('`

Потім я виявив, що я неправильно додав пробіл у команді.

Але чому ця додаткова команда призведе до цього провалу? Чому символ переадресації повинен бути близьким до (?


Слід зазначити, що оболонки * nix розбивають речі на основі пробілів, що створює маркери, про які згадував Алек.
пташенята

Відповіді:


45

Тому що це не є <, це <()зовсім інше. Це називається заміщенням процесу , це особливість певних оболонок, що дозволяє використовувати вихід одного процесу як вхід для іншого.

Оператори >і <оператори переадресовують вихід і введення файлів . <()Оператор має справу з командами (процеси), а не файл. Коли ти біжиш

sort < (ls)

Ви намагаєтеся запустити команду lsв підклітині (саме це означають круглі дужки), а потім передати цю підпакет як вхідний файл sort. Це, однак, не приймається синтаксисом, і ви отримуєте помилку, яку ви побачили.


3
Ваша відповідь хороша, але then sort is attempting to read the subshell as its input file→ це, очевидно, неправильно, оскільки Bash навіть не розбере синтаксис. Ні, lsні sortнасправді не виконується.
sleblanc

1
@sebleblanc справедлива точка, перефразовуючи відповідь, дякую.
тердон

1
У цьому випадку немає підрозділу. < (ls)тут не дійсний маркер.
cuonglm

@cuonglm ні, тому що bash трактує це як синтаксичну помилку. Моя думка полягає в тому, що він (ls)би працював lsу передпласті.
тердон

22

Тому що так мається бути.

<(...)в bash- це синтаксис заміщення процесу. Він скопійований з того самого оператора в ksh.

<, (, ), |, &, ;Спеціальні лексичні маркери в bashякі використовуються для формування спеціальних операторів в різних комбінаціях. <, <(, <<, <&... кожен має свою роль. <призначений для перенаправлення. <file, < fileбуде перенаправляти введення з файлу. <'(file)'буде перенаправляти вхід з файла, який називається (file), але <(file)це інший оператор, який не є оператором перенаправлення.

< (file)буде <слідувати (file). У цьому контексті, в bash, (file)не вірно. (...)може бути дійсним як один маркер у деяких контекстах, таких як:

(sub shell)
func () {
  ...
}
var=(foo bar)

Але не в

sort < (cmd)

У fishшкаралупі все інакше. В fish, (...)призначений для підстановки команд (еквівалент $(...)в bash). І <призначений для перенаправлення вводу, як у оболонок, подібних до Борна.

Так у fish:

sort <(echo file)

буде те саме, що:

sort < (echo file)

Це є:

sort < file

Але це щось зовсім інше, ніж bashпроцес заміщення Росії.

В yashоболонці, інший POSIX оболонка, <(...)не для заміщення процесу , але і для перенаправлення процесу

Там,

sort <(ls -l)

Короткий термін для:

sort 0<(ls -l)

є оператором перенаправлення. Це більш-менш еквівалентно:

ls -l | sort

Перебуваючи в bash, <(ls -l)розгорнуто до шляху труби, тож це більше схоже на:

ls -l | sort /dev/fd/0

В zsh, (...)перевантажений як оператор будуються по ( (*.txt|*.png)буде розширюватися txtі pngфайли) , а також Глоб класифікатором ( *(/)наприклад , розширюється до файлів каталогу).

В zsh, в:

sort < (ls -l)

Це (ls -l)трактується як глобальний класифікатор. lГлоб класифікатор повинен відповідати за кількістю посилань і очікує , що число після l(як ls -ld ./*(l2)би список файлів з 2 посилання), так ось чому ви отримаєте zsh: number expectedпомилку там.

sort < (w)zsh: no matches found: (w)натомість дав би помилку як (w)збіг файлів із порожнім ім'ям, які можна записати.

sort < (w|cat)сортував би вміст wта / або catфайлів у поточному каталозі ...


чому sort < $(ls -l)дає цю помилку:bash: $(ls -l): ambiguous redirect
Едвард Торвальдс

@edwardtorvalds, оскільки $(ls -l)розширюється на більше ніж одне слово. Використовуйте лапки, щоб запобігти спліт + glob ( sort < "$(echo file)"). Зауважте, що поведінка або bashвідрізняється від POSIX sh у тому, що bash робить розкол + glob там також, коли не інтерактивний (не коли викликається як shби).
Стефан Шазелас

переглянувши, ls -l | sort /dev/fd/0я можу сказати, що вихідний ls -lфайл зберігається /dev/fd/0і sortкоманда читає його, щоб дати бажаний вихід. Я використовую tail -f --retry /dev/fd/0для моніторингу цього файлу, але не отримую жодного результату. чому? як я можу прочитати цей файл?
Едвард Торвальдс

У рибі можна використовувати (foo | psub)для досягнення заміни вхідного процесу; ще немає замінника (га) для заміщення вихідного процесу.
Занчі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.