Когда я пытаюсь это сделать на своем компьютере с Linux, я получаю противоречивые результаты. Иногда 123, иногда (в большинстве случаев) 23, иногда 12. Это тонкое условие буферизации расы между самым правым xargs
и любым из sed
, которое оно порождает.
Рассечение командной строки:
ls y*
выведет 4 строки, y, y1, y2 и y3; буферизация не актуальна
xargs -i basename {}
прочитает их и запустит, в последовательности, basename y
, basename y1
, basename y2
, basename y3
; выходные данные, так же как и входные в нашем случае, буферизуются по строкам, так как каждая строка происходит из другого процесса.
xargs -i sed "s/{}//g"
, для каждой строки X, которую он читает (подробнее об этом позже), запускается sed "s/X//g"
- каждый
sed "s/X//g"
отфильтровывает каждый X в строках, которые он читает
Где это сложно: две последние команды читают ввод из одного и того же потока. Этот поток создается несколькими различными процессами в последовательности. В зависимости от множества факторов (загрузка системы, планирование) выходные данные могут выходить с очень разными временными диаграммами.
Предположим, они все очень быстрые. Тогда все четыре строки могут быть доступны для правого xargs
для чтения в одном блоке. В этом случае не осталось бы ввода для чтения любого из sed
, следовательно, вообще не выводит .
С другой стороны, если бы они были очень медленными, для правой стороны xargs
могла бы быть доступна только одна строка при первой попытке чтения. Эта строка будет "у". xargs
будет порождать первое sed
как sed "s/y//g"
, которое будет использовать все оставшиеся входные данные (y1, y2, y3), полосы y
и выходные данные 1, 2, 3 . Вот то же самое объяснение снова с более явным упорядочением.
- first
basename
пишет "y".
- вправо
xargs
читает "y", порождает sed s/y//g
. xargs
теперь ожидает завершения sed
.
- секунда
basename
пишет "y1"; sed
читает "y1", пишет "1"
- третий
basename
пишет "y2"; sed
читает "y2", пишет "2"
- четвертый
basename
пишет "y3"; sed
читает "y3", пишет "3"
- осталось
xargs
готово; sed
читает EOF и останавливается
- вправо
xargs
пытается продолжить, читает EOF и останавливается
Не уверен насчет моего 12 случая. Возможно, GNU xargs
не дожидается завершения своих потомков, прежде чем прочитает последующие доступные данные, и вырвал строку "y3" из первого sed
.
В любом случае вы просто настраиваете конвейер с несколькими одновременными считывателями на одном и том же устройстве записи , что дает в основном недетерминированные результаты. Избегать.
Если бы вы хотели работать с каждым из файлов, этого можно было бы избежать, указав имя файла для использования sed
(обратите внимание на окончательный {}):
ls y* | xargs -i basename {} | xargs -i sed "s/{}//g" {}
Если то, что вы хотели, было результатом по кросс-типу продукта (уберите каждое имя файла из каждого файла), вам нужно было бы сделать так, чтобы список файлов создавался столько раз, сколько существует файлов. Плюс один для xargs
, если вы все еще использовали это.
Надеюсь, это поможет.