Как связать стандартный ввод и строку?

108

Как связать стандартный ввод со строкой, как это?

echo "input" | COMMAND "string"

и получить

inputstring
Ноам Росс
источник

Ответы:

119

Немного хакерский, но это может быть самый короткий способ сделать то, что вы задали в вопросе (используйте канал для принятия stdoutот echo "input"as stdinк другому процессу / команде:

echo "input" | awk '{print $1"string"}'

Вывод:

inputstring

Какую задачу вы конкретно пытаетесь выполнить? Более подробный контекст поможет вам найти лучшее решение.

Обновление - ответ на комментарий:

@NoamRoss

Тогда более идиоматический способ сделать то, что вы хотите:

echo 'http://dx.doi.org/'"$(pbpaste)"

$(...)Синтаксис называется подстановка команд . Короче говоря, он выполняет команды, заключенные в новую подоболочку, и заменяет свой stdoutвывод там, где $(...)был вызван в родительской оболочке. Таким образом, вы получите:

echo 'http://dx.doi.org/'"rsif.2012.0125"
Сампсон-Чен
источник
1
Спасибо! Это прекрасно работает. Точная задача, которую я пытаюсь выполнить, - взять строку из буфера обмена (DOI) и добавить к ней URL-адрес, так что с этим я делаю pbpaste | awk '{print "http://dx.doi.org/"$1}'и получаюhttp://dx.doi.org/10.1098/rsif.2012.0125
Ноам Росс,
5
@ sampson-chen, я бы '{print $0"string"}'схватил все это.
Роман Ньюаза
3
Фактически он добавляется stringк каждой строке. Попробуй echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi 03
56

используйте cat -для чтения из stdin и вставьте его, $()чтобы выбросить завершающую новую строку

echo input | COMMAND "$(cat -)string"

Однако почему бы вам не отбросить трубу и не захватить вывод левой части подстановкой команды:

COMMAND "$(echo input)string"
Гленн Джекман
источник
1
Вот практический пример: найдите ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Эшвин Джаяпракаш,
2
У меня это работает в bash, но в zsh я получаю «cat: -: Ошибка ввода / вывода». Есть идеи, что могло вызвать это?
jaymmer
«КОМАНДА» означает решение, а «эхо-ввод» - более сложный процесс. Аргумент «-» для cat требуется, только если есть другие аргументы файла, в противном случае он используется по умолчанию. Итак, вы имели в виду: эхо-ввод | echo $ (cat) string
Денис Хоу
46

Я часто использую каналы, поэтому это простой способ добавить префикс и суффикс stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix
rupert160
источник
2
Спасибо! На самом деле это очень крутой пример использования pipeиcat
Alex Ivasyuv
1
Это должен быть лучший ответ
Крис Костон
1
Почему не просто echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? Или, более читаемая версия:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax
1
@MiniMax Поскольку ответ хорошо работает с потоками, он будет работать для большого стандартного ввода.
анишпател 04
1
@anishpatel Моя версия будет работать и для большого стандартного ввода. Нет разницы.
MiniMax 04
11

Вы можете сделать это с помощью sed:

seq 5 | sed '$a\6'
seq 5 | sed '$ s/.*/\0 6/'

В вашем примере:

echo input | sed 's/.*/\0string/'
Витенис Биваинис
источник
9

Есть несколько способов добиться этого, я лично считаю, что лучший из них:

echo input | while read line; do echo $line string; done

Другой может быть заменой «$» (символ конца строки) на «строку» в команде sed:

echo input | sed "s/$/ string/g"

Почему я предпочитаю первое? Потому что он мгновенно объединяет строку со стандартным вводом, например, с помощью следующей команды:

(echo input_one ;sleep 5; echo input_two ) | while read line; do echo $line string; done

вы сразу получите первый вывод:

input_one string

а затем через 5 секунд вы получите другое эхо:

input_two string

С другой стороны, при использовании "sed" сначала выполняется все содержимое круглой скобки, а затем оно передается в "sed", поэтому команда

(echo input_one ;sleep 5; echo input_two ) | sed "s/$/ string/g"

выведет обе строки

input_one string
input_two string

через 5 секунд.

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

Симона
источник
Фактически, опция sed также мгновенно обрабатывает каждую строку ввода.
tomekwi 03
Для одной строки ввода самым простым решением является ввод эхо | (читать v; echo $ {v} string) Это чистая оболочка, поэтому не требуется дополнительных процессов, таких как sed.
Денис Хоу
7

Я знаю, что это опоздание на несколько лет, но вы можете сделать это с помощью опции xargs -J:

echo "input" | xargs -J "%" echo "%" "string"

А так как это xargs, вы можете сделать это на нескольких строках файла одновременно. Если в файле name есть три строки, например:

Adam
Bob
Charlie

Вы могли сделать:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"
пользователь2635263
источник
1
Выглядит круто, но -Jне кажется стандартным / обычным. В Linux (где xargsэто часть GNU findutils) я получаю сообщение об ошибке: На xargs: invalid option -- 'J'какой это системе?
arielf
3
-Jдля версии для Mac. Для Linux -Iвыполняет ту же функцию.
user2635263
1
Спасибо! очень полезно. Обратите внимание, что в Linux эта упрощенная версия работает так же хорошо: cat names | xargs -I% echo "I like % because he is nice"IOW: нет необходимости в -n 1( в любом случае xargsвызывает echoодин раз для каждой строки ввода, поскольку -Iподразумевает -L1) Кроме того, все отдельные кавычки аргументов кажутся избыточными.
arielf
3

Опубликованная вами команда примет строку «input» и будет использовать ее как поток stdin КОМАНДЫ, который не даст результатов, которые вы ищете, если только COMMAND сначала не распечатает содержимое своего stdin, а затем распечатает аргументы командной строки.

Похоже, то, что вы хотите сделать, ближе к подстановке команд.

http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html#Command-Substitution

При подстановке команд вы можете получить такую ​​командную строку:

echo input `COMMAND "string"`

Это сначала оценит КОМАНДУ с "строкой" в качестве входных данных, а затем развернет результаты выполнения этой команды на строку, заменив то, что находится между символами '' '.

Макс ДеЛисо
источник
и, конечно же, @NaomRoss, если вам не требуется использовать оболочку Bourne или у вас есть другие безумные требования "переносимости", вы будете использовать современную подстановку команд, например echo input $(COMMAND "string"), а не обратные кавычки. Всем удачи.
Shellter
1

кот будет моим выбором: ls | cat - <(echo new line)

Clarkttfu
источник
sed - это строчная команда, которая не работает, если восходящий канал ничего не выводит ..
clarkttfu
0

Также работает:

seq -w 0 100 | xargs -I {} echo "string "{}

Будет генерировать такие строки, как:

string 000
string 001
string 002
string 003
string 004

...

cy8g3n
источник