Можно ли использовать вывод канала в качестве аргумента сценария оболочки?
Предположим, у меня есть скрипт оболочки bash с именем Myscript.sh
что нужен один аргумент в качестве входных данных.
Но я хочу, чтобы содержимое текстового файла называлось text.txt
быть этим аргументом.
Я пробовал это, но это не работает:
cat text.txt | ./Myscript.sh
Есть ли способ сделать это?
10 ответов
Вы можете использовать вывод канала в качестве аргумента сценария оболочки.
Попробуйте этот метод:
cat text.txt | xargs -I {} ./Myscript.sh {}
Чтобы завершить @bac0n, который, по моему мнению, единственный, кто правильно отвечает на вопрос, вот короткий лайнер, который добавит переданные по конвейеру аргументы в список аргументов вашего скрипта:
#!/bin/bash
declare -a A=("$@")
[[ -p /dev/stdin ]] && { \
mapfile -t -O ${#A[@]} A; set -- "${A[@]}"; \
}
echo "$@"
Пример использования:
$ ./script.sh arg1 arg2 arg3
> arg1 arg2 arg3
$ echo "piped1 piped2 piped3" | ./script.sh
> piped1 piped2 piped3
$ echo "piped1 piped2 piped3" | ./script.sh arg1 arg2 arg3
> piped1 piped2 piped3 arg1 arg2 arg3
Направьте это вxargs
перед фактической командой, напримерcat text.txt | xargs ./Myscript.sh
Если в файле более одной команды, рассмотрите возможность использования xargs или параллельного кода, например
xargs -d '\n' Myscript.sh < text.txt
parallel -j4 Myscript.sh < text.txt
Читая stdin с mapfile, вы можете переустановить позиционные параметры.
#!/bin/bash
[[ -p /dev/stdin ]] && { mapfile -t; set -- "${MAPFILE[@]}"; }
for i in $@; do
echo "$((++n)) $i"
done
(Цитата "$@" сделает for
линии цикла вместо).
$ cat test.txt | ./script.sh
1 one
2 two
3 tree
Этот вопрос немного устарел, но я нашел это решение наиболее простым для понимания и хотел поделиться им.
Если вы хотите принять содержимоеtest.txt
в качестве входных данных для вашего сценария (например,cat test.txt | ./myEchoScript
), вы можете сделать следующее, чтобы прочитать из стандартного ввода
if [ -p /dev/stdin ]; then
input=$(cat)
else
echo "expecting input to be piped in, exiting script"
exit
fi
echo $input
Затем запустить:
$ echo "testing testing" > test.txt
$ cat test.txt | ./myEchoScript.sh
testing testing
Пытаться,
$ cat comli.txt
date
who
screen
wget
$ cat comli.sh
#!/bin/bash
which $1
$ for i in `cat comli.txt` ; do ./comli.sh $i ; done
так что вы можете ввести значения по одному, чтобы comli.sh
от comli.txt
,
Если в файле есть символы новой строки (LF) или табуляции, и вы хотите фактически поместить их в один аргумент (не заставлять bash конвертировать LF в пробелы и использовать каждое слово в качестве отдельного аргумента), вы можете использовать это:
./Myscript.sh "$(IFS=''; cat text.txt)"
(используется подоболочка, поэтому IFS не затрагивается в основной оболочке)
Простой тест, показывающий, что это работает:
echo ">>>$(IFS=''; cat text.txt)<<<"
Версия без оболочки:
IFS=" " ; echo ">>>$(cat text.txt)<<<" ; IFS=$' \t\n'
См. также: https://stackoverflow.com/questions/2789319/file-content-into-unix-variable-with-newlines
Процесс замены
./Myscript.sh <(cat text.txt)
Смотрите, например, https://www.gnu.org/software/bash/manual/bash.html