Новые разделенные строкой параметры рассматриваются как один позиционный параметр в сценарии оболочки - PullRequest
0 голосов
/ 18 марта 2020

У меня есть bash скрипт myScript.sh, который просто печатает первый параметр скрипта:

$  cat file.txt
1
2
3
4 

$  cat myScript.sh
#!/bin/bash
echo $1

И если я запускаю скрипт, он возвращает то, что я ожидаю:

$ cat file.txt | xargs ./myScript.sh
1

однако, если я пытаюсь сохранить новые строки в исходном файле, список передается как позиционный параметр one в сценарий оболочки.

$  cat file.txt | xargs -0 ./myScript.sh
1 2 3 4

I'm интересно, что вызывает такое поведение? Также похоже, что в этом случае входной список получил неявное разделение полей (аналогично тому, что происходит при подстановке команд).

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

Задача xargs, предназначенная для решения, заключается в том, что существует ограничение на размер командной строки оболочки. И этот предел был довольно маленьким. В наши дни ограничение достаточно велико, но вы все равно можете достаточно легко его превысить, и в этом случае xargs по-прежнему является полезным инструментом.

Так что xargs ожидает, что вызываемая команда может принимать несколько параметров и использовать их все. Это довольно часто; рассмотрим grep или ls -l или wc или ... Что делает xargs, так это многократно собирает столько аргументов, сколько может поместиться в вызове команды, и вызывает команду со всеми из них.

Таким образом, он принимает входной поток, состоящий из ряда аргументов. По умолчанию эти аргументы разделяются пробелами, поэтому в строке может быть несколько аргументов. Но поскольку в наши дни в именах файлов чаще встречаются пробелы, эта функция xargs стала помехой. Можно было бы сделать каждую строку во входном файле отдельным аргументом, но наиболее общим решением является разделение аргументов символом NUL, что позволяет аргументу включать символ новой строки.

(Аргументы к утилитам оболочки не могут включать символы NUL. Поэтому использование NUL в качестве разделителя не добавляет никаких ограничений.)

Вы можете задать xargs ваше собственное максимальное количество аргументов для использования для один вызов. И вы даже можете установить этот максимум на 1. Таким образом, вы можете, если хотите, использовать xargs, чтобы запустить команду для каждого из аргументов в файле. Это иногда полезно, но не очень эффективно. Обычно лучшим решением является написание команд для нескольких аргументов, как в оригинальном проекте. Но если вы хотите использовать xargs таким образом, посмотрите опцию командной строки -n, среди других возможностей.

1 голос
/ 19 марта 2020

Поведение, которое вы видите, является нормальным поведением.

Первый набор команд:

cat file.txt | xargs ./myScript.sh

xargs собирает аргументы и запускает следующие команды

./myScript.sh "1" "2" "3" "4"

, что довольно легко понять.

Второй набор команд:

cat file.txt | xargs -0 ./myScript.sh

Поскольку в файле file.txt нет символов NUL, xargs собирает весь стандартный ввод и выполняет следующую команду с одним Аргумент:

./myScript.sh $'1\n2\n3\n4\n'

Аргумент хорошо содержит символы новой строки, которые вы хотели сохранить.

Но команда, введенная вами в myScript. sh, заставляет его показывать, что символов новой строки нет.

Если вы измените myScript. sh следующим образом:

$  cat myScript.sh
#!/bin/bash
echo -n "$1"

Вы увидите новые строки.

...