Котяча команда та відлуння


14

Я хотів би поєднати вихід із луною із вмістом файлу. Я спробував наступне командування:

echo "abc" | cat 1.txt > 2.txt

але 2.txtфайл містить лише вміст від 1.txt. Чому це не працює?


3
Такі програми, як catчитати лише зі стандартного введення, якщо у них немає аргументів імені файлів.
Бармар

Відповіді:


23

Це не працює, тому що catпрограма у послідовності вашої труби не була доручена зчитувати echoвихідні дані програми зі стандартного вводу.

Ви можете використовувати -як ім'я файлу псевдо для вказівки стандартного введення cat. З man catвстановлення msys2:

EXAMPLES
       cat f - g
              Output f's contents, then standard input, then g's contents.

Тож спробуйте

echo "abc" | cat - 1.txt > 2.txt

замість цього.


21

Як зазначають інші, ваша оригінальна команда не працює, оскільки cat 1.txtнехтує її стандартним вводом. Або вкажіть, що це повинен бути його перший аргумент ( cat - 1.txt), або використовуйте блокове перенаправлення для переадресації echo abc та cat 1.txt разом. А саме:

{ echo abc; cat 1.txt; } > 2.txt 

Відповідний уривок з посібника ( man bash):

Складені команди Складені команди
є одним із наступних. У більшості випадків список в описі команди може бути відокремлений від решти команди одним або декількома новими рядками, а після цього крапкою з комою може слідувати новий рядок.

(список)

    список виконується в середовищі додаткової оболонки (див. КОМАНДУ ВИКОНАВЧОГО ЕКОЛОГІЇ нижче). Змінні призначення та вбудовані команди, які впливають на середовище оболонки, не залишаються в силі після завершення команди. Статус повернення - це статус виходу зі списку.

{список; }

    список просто виконується в поточному середовищі оболонки.  список повинен бути завершений новим рядком або крапкою з комою. Це відомо як команда групи . Статус повернення - це статус виходу зі списку . Зауважте, що на відміну від метахарактерів (і ), {і }є зарезервованими словами, вони повинні виникати там, де дозволено розпізнавати зарезервоване слово. Оскільки вони не викликають розрив слова, їх потрібно відокремити від списку пробілом або іншим метахарактером оболонки.

Перший варіант (середовище додаткової оболонки) має купу побічних ефектів, більшість з яких не всі стосуються вашого сценарію; однак, якщо все, що вам потрібно, перенаправлення виводу з команд - це варіант №2 (команда групи).


7
( echo "abc"; cat 1.txt ) > 2.txt

Ви передали ехо-виведення коту, але кіт не мав користі для введення даних і проігнорував це. Тепер команди виконуються одна за одною, а їх вихід групується (в дужках) і спрямовується в 2.txt.


1
Цю відповідь можна покращити, пояснивши, як вона працює, і чому оригінальна спроба ОП не працює.
Боб

Гаразд, спробував.
Джерард Х. Піл

5
Тут прямо не потрібно додаткової оболонки, можливо, було б краще використовувати команду групи. Дивіться мою відповідь для більш детальної інформації.
Нубарке

Ах, але я ніколи не використовую баш.
Джерард Х. Піл

1
@ GerardH.Pille: Хоча відповідь Даніеля цитує bash(1), він описує поведінку, яку повинна підтримувати кожна сумісна з POSIX оболонка.
G-Man каже: "Відновіть Моніку"

2

Ваша команда cat 1.txtнічого не робить з результатом echo "abc".

Замість цього: (echo "abc"; cat 1.txt) > 2.txt запишемо вихід обох команд у 2.txt.


Цю відповідь можна покращити, пояснивши, як працює запропонована альтернатива.
Боб

1

У будь-якій оболонці POSIX ви можете використовувати заміну команд, щоб використовувати cat fileяк вхід для echo:

echo $(cat file1.txt) "This Too"

У Bash ви можете використовувати підстановку процесу та використовувати echo як інший "файл" для cat, як у:

cat file1.txt <(echo This Too)

а потім трубуйте або перенаправляйте вихід, як вважаєте за потрібне.

Як і кожна інша відповідь, кішка ігнорує stdin, якщо у нього є файл, який потрібно подивитися. (Мені також подобаються відповіді Даніеля та mvw, +1 для них)


1
Цю відповідь можна покращити, пояснивши, чому оригінальна спроба ОП не працює (і, чому, натомість, це потрібно).
Боб

1
<(command)Конструкція є продовженням Баша. Це не POSIX, тому ви не можете покластися на нього в сценаріях, які повинні бути виконані /bin/sh.
Ріалто підтримує Моніку

0

Лише здогадка, але схоже, що у вас є повторюваний процес, який є хорошим кандидатом на псевдонім або функцію. Псевдоніми - це зазвичай короткі скорочення для виклику команд bash, таких як абревіатура, на одному вхідному потоці як його аргументі.

alias hg="history | grep"

Однак у цьому випадку функція буде більш читаною, оскільки ви поєднуєте кілька, дискретних (2) вхідних потоків, а також декілька команд bash. У вас є два аргументи: перший - це рядок, а другий - шлях. Зрештою, ви хочете, щоб результат був записаний у вихідний потік stdout.

У рядку CLI введіть це:

# ecat()        
{
echo ${1}
cat ${2}
}

Ваша функція названа ecat, що запам'ятовується.

Тепер ви можете викликати як

ecat "abc" 1.txt

Щоб додати, просто введіть інше місце виводу для stdout:

ecat "abc" 1.txt >> 2.txt

Оператор додавання переадресації '>>' додасть вихід до кінця вказаного файлу.

Якщо вам це подобається, додайте файл ~ / .bashrc для повторного використання.

declare -f ecat >> ~/.bashrc

Це також означає, що ви можете прикрасити тощо у межах свого визначення функції.

Також хороша ідея захистити файли від перезапису, додавши це до вашого ~ / .bashrc

set noclobber

2
Щоб ваша функція поводилася належним чином, слід використовувати "$1"і "$2". У цьому контексті фігурні брекети не приносять користі. Бачити ${name}не означає, що ви думаєте, що це робить… .
G-Man каже: "Відновіть Моніку"

1
Як noclobberпропозиція відповідає на відповідне питання? (Я також дуже не переконаний, що це гарна порада - модифікація глобальної поведінки має тенденцію порушувати сценарії / поради / практики, побудовані з урахуванням значень за замовчуванням).
Чарльз Даффі

0

Наступний код також буде працювати:

echo abc >> 1.txt && cat 1.txt > 2.txt

Вихід echo abc буде доданий до 1.txt з >> Після цього && скаже йому виконати наступний набір команд, який введе кодування 1.txt, а потім виведе його на 2.txt . В основному, він додає висновок першої команди в 1.txt і потім відправляє вихід 1.txt в 2.txt.

Якщо ви хочете, щоб abc з'явився першим, ви можете використовувати такий код:

echo abc >> 2.txt && cat 1.txt >> 2.txt

1
Це буде (1) помістити abcв нижній частині 2.txt; питання хоче цього вгорі. (2)  зміни в 1.txtфайл; це неприпустимо.
G-Man каже «Відновити Моніку»

Де це говорить? Ringger81 ніколи не вказував, де в 2.txt він хотів з'явитися abc. Ви припускаєте речі, про які жодне питання не йдеться.
Насір Райлі

(1) Гаразд, ви піднімаєте дійсну точку на №1. Хоча в питанні згадується "вихід із відлуння" перед "вмістом файлу" в тексті, а потім ставиться echoперед перед catзразком команди, я вважаю, що він ніколи точно, явно , не говорить, що він хоче виводити з ехо перед вміст вхідного файлу. Просто здається, що більшість людей так трактували це. (2)  1.txt- вхідний файл. Питання нічого не говорить про зміни 1.txt. Те, що вхідні файли не слід змінювати, само собою зрозуміло.
G-Man каже: "Відновіть Моніку"

Я можу зрозуміти вашу думку щодо того, щоб не змінювати файл вводу. Мій другий код досягне бажаного ефекту, не роблячи цього.
Насір Райлі

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