Як об'єднати stdin і рядок?


108

Як зв'язати stdin з рядком, як це?

echo "input" | COMMAND "string"

і дістати

inputstring

Відповіді:


119

Трохи Hacky, але це може бути самий короткий шлях , щоб зробити те , що ви просили в цьому питанні (використовуйте трубку , щоб прийняти stdoutвід , echo "input"як 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

55

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

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

Однак чому б вам не кинути трубу і захопити вихід лівої сторони в підстановці команд:

COMMAND "$(echo input)string"

1
Ось практичний приклад: знайдіть ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | відлуння "$ (кіт -) ~ / java_app / класи"
Ashwin Jayaprakash

2
Це працює для мене в bash, але в zsh я отримую "cat: -: Помилка введення / виводу". Будь-яка ідея, що може спричинити це?
джеймер

"COMMAND" означає рішення та "ехо-введення" для деяких складніших процесів. Аргумент "-" для cat потрібен лише за наявності інших аргументів файлів, інакше це за замовчуванням. Отже, що ви мали на увазі: відлуння введення | echo $ (cat) string
Denis Howe

46

Я часто використовую труби, тому це, як правило, простий спосіб префікса і суфікса stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix

2
Дякую! Це насправді дуже класний приклад використання pipeтаcat
Олексій Івасюв

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 Оскільки відповідь добре працює з потоками, вона буде працювати для великих stdin.
anishpatel

1
@anishpatel Моя версія також буде працювати для великих stdin. Без різниці.
MiniMax

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"

Чому я віддаю перевагу колишньому? Оскільки він об'єднує рядок, щоб stdin миттєво, наприклад, з наступною командою:

(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

Для одного рядка введення найпростішим рішенням є введення відлуння | (read v; echo $ {v} string) Це чиста оболонка, тому не потрібен додатковий процес, як sed.
Деніс Хоу

7

Я знаю, що це запізнюється на кілька років, але ви можете досягти цього за допомогою параметра xargs -J:

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

А так як це xargs, ви можете зробити це на декількох рядках файлу одночасно. Якщо файл 'імена' має три рядки, наприклад:

Adam
Bob
Charlie

Ви можете зробити:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"

1
Виглядає круто, за винятком випадків, що -Jце не є стандартним / поширеним. У Linux (де xargsце частина GNU findutils) я отримую помилку: для xargs: invalid option -- 'J'якої системи це?
аріельф

3
-Jпризначений для версії Mac. Для Linux -Iвиконує ту ж функцію.
користувач2635263

1
Дякую! дуже корисний. Зауважте, що в Linux ця спрощена версія працює так само добре: cat names | xargs -I% echo "I like % because he is nice"IOW: немає необхідності -n 1( xargsдзвінки echoодин раз за рядком введення, оскільки це -Iозначає -L1) Також, все окреме цитування аргументів здається зайвим.
аріельф

3

Команда, яку ви розмістили, приймає рядок "input", використовуючи його як stdin-потік COMMAND, який не дасть результатів, які ви шукаєте, якщо COMMAND спочатку не надрукував вміст свого stdin, а потім роздрукував його аргументи командного рядка.

Схоже, те, що ви хочете зробити, є більш близьким до заміни команд.

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

З підстановкою команд у вас може бути такий командний рядок:

echo input `COMMAND "string"`

Це спочатку оцінить COMMAND за допомогою "string" як вхідного даних, а потім розширить результати виконання цих команд на рядок, замінивши те, що між символами '' '.


і звичайно @NaomRoss, якщо вам не потрібно використовувати оболонку Bourne або мати інші божевільні мандати на "переносимість", ви використовуєте сучасну підстановку команд на кшталт echo input $(COMMAND "string"), а не backticks. Успіхів усім.
обстріл

1

кішка буде моїм вибором: ls | cat - <(echo new line)


sed - це командна лінія, яка не працює, якщо труба вище за течією не має нічого виходу ..
clarkttfu

0

Також працює:

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

Буде створювати рядки, такі як:

string 000
string 001
string 002
string 003
string 004

...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.