10

Я хотел бы объединить вывод из echo с содержимым файла. Я попробовал следующую команду:

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

но файл 2.txt содержит только содержимое из 1.txt . Почему это не работает?

7 ответов7

20

Это не работает, потому что программе 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

вместо.

16

Как отмечали другие, ваша оригинальная команда не работает, потому что cat 1.txt игнорирует ее стандартный ввод. Либо укажите, что это должен быть его первый аргумент (cat - 1.txt), либо используйте перенаправление блоков для перенаправления echo abc и cat 1.txt вместе. Для остроумия:

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

Соответствующая выдержка из руководства (man bash):

Составные команды
Составная команда является одной из следующих.  В большинстве случаев список в описании команды может быть отделен от остальной части команды одним или несколькими символами новой строки и может сопровождаться символом новой строки вместо точки с запятой.

( список )

    Список выполняется в среде оболочки (см. ниже КОМАНДА ИСПОЛНИТЕЛЬНОЙ СРЕДЫ). Переменные и встроенные команды, которые влияют на среду оболочки, не остаются в силе после ее завершения.  Статус возврата - это статус выхода из списка.

{ список ; }

    Список просто выполняется в текущей среде оболочки.  список должен заканчиваться символом новой строки или точкой с запятой.  Это известно как групповая команда.  Статус возврата - это статус выхода из списка.  Обратите внимание, что в отличие от метасимволов ( и ), { и } являются зарезервированными словами и должны встречаться там, где зарезервированное слово разрешено распознавать.  Поскольку они не вызывают разрыв слова, они должны быть отделены от списка пробелами или другими метасимволами оболочки.

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

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

Вы передали вывод эха в cat, но cat не использовал ввод и проигнорировали его. Теперь команды выполняются одна за другой, и их выходные данные группируются (круглые скобки) и направляются в 2.txt.

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)

а затем направьте или перенаправьте вывод, как считаете нужным.

Как и в любом другом ответе, cat игнорирует стандартный ввод, если у него есть файл для просмотра. (Мне тоже нравятся ответы Даниэля и mvw, +1 за них)

0

Следующий код также будет работать:

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

Вывод echo abc будет добавлен в 1.txt с помощью >>. После этого && скажет ему выполнить следующий набор команд, который будет cat 1.txt, а затем выведет его в 2.txt. По сути, он добавляет вывод первой команды в 1.txt, а затем отправляет вывод 1.txt в 2.txt.

Если вы хотите, чтобы abc появлялся первым, вы можете использовать следующий код:

echo abc >> 2.txt && cat 1.txt >> 2.txt
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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .