猫命令和回声


14

我想将echo的输出与文件的内容连接起来。我尝试了以下命令:

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

但该2.txt文件仅包含中的内容1.txt。为什么不起作用?


3
cat仅从标准输入读取程序的程序,如果它们没有任何文件名参数。
Barmar

Answers:


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):

复合命令
复合命令是以下命令之一。在大多数情况下,命令描述中的列表可以用一个或多个换行符与命令的其余部分分隔开,并且可以用换行符代替分号。

(清单)

    list是在子shell环境中执行的(请参阅下面的COMMAND EXECUTION ENVIRONMENT)。在命令执行完成后,影响外壳环境的变量分配和内置命令将保持无效。返回状态是列表的退出状态。

{清单; }

    list仅在当前的shell环境中执行。  列表必须以换行符或分号终止。这称为组命令。返回状态是list的退出状态。请注意,与元字符(和和不同){和和}保留字,并且必须在允许识别保留字的地方出现。由于它们不会造成单词中断,因此必须使用 空格或其他shell元字符将它们与list分开。

第一个选项(subshel​​l环境)有很多副作用,大多数(如果不是全部)与您的情况无关;但是,如果只需要重定向一堆命令的输出,则首选此处的选项2(组命令)。


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

您将回声输出通过管道传递给cat,但是cat对输入没有用,并忽略了它。现在,这些命令一个接一个地运行,并且它们的输出被分组(括号)并定向到2.txt中。


1
这个答案可以通过解释来改善如何它的工作原理和为什么的OP原来的尝试不起作用。
鲍勃

好的,尝试一下。
Gerard H. Pille

5
这里没有明确要求使用subshel​​l,也许最好使用group命令。请参阅我的答案以获取更多详细信息。
Nubarke

啊,但是我永远不会使用bash。
Gerard H. Pille

1
@ GerardH.Pille:虽然Daniel的回答引用了bash(1),但它描述了每个POSIX兼容外壳程序必须支持的行为。
G-Man说'Resstate Monica'18'Jan

2

您的命令cat 1.txt对的输出不执行任何操作echo "abc"

而是: (echo "abc"; cat 1.txt) > 2.txt 将两个命令的输出都写入2.txt。


可以通过解释建议的替代方法如何改进此答案。
鲍勃

1

在任何POSIX shell中,都可以使用命令替换cat file作为以下命令的输入echo

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

在Bash中,您可以使用进程替换并将echo用作的另一个“文件” cat,如下所示:

cat file1.txt <(echo This Too)

然后根据需要通过管道传输或重定向输出。

就像其他所有答案一样,如果要查看的文件,cat会忽略stdin。(我也非常喜欢Daniel&mvw的答案,为他们+1)


1
可以通过解释为什么OP的原始尝试不起作用(以及为什么必须这样做)来改进此答案。
鲍勃

1
<(command)结构是bash扩展。它不是POSIX,因此您不能在应该使用执行的脚本中依赖它/bin/sh
Rhialto支持Monica

0

只是一个猜测,但是看起来您有一个可重复的过程,这是别名或函数的理想选择。别名通常是在单个输入流上作为其参数调用bash命令(如缩写)的捷径。

alias hg="history | grep"

但是,在这种情况下,由于您要合并多个离散(2)输入流以及多个bash命令,因此函数的可读性更高。您有两个参数,第一个是字符串,另一个是文件路径。最后,您希望将结果写入标准输出输出流。

在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说'恢复莫妮卡''18

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说'恢复莫妮卡''18

它在哪里说呢?Ringger81从未指定他要abc在2.txt中出现的位置。您假设问题从未阐明。
Nasir Riley

(1)好,您在#1上提出一个有效点。虽然这个问题提到了“从回声输出”,“文件的内容”前的文本,然后放echo前的cat样品命令,我想它永远不会确切地,明确地说,它希望从回波前的输出输入文件的内容。似乎大多数人都这样解释。(2)  1.txt是输入文件。这个问题没有说明修改1.txt。不应该修改输入文件的事实是不言而喻的。
G-Man说'Resstate Monica''18

我可以理解您关于不修改输入文件的观点。我的第二个代码无需这样做即可达到预期的效果。
Nasir Riley

1
打开文件,附加到文件,关闭文件,再次打开文件,再附加到文件...为什么这样做而不是只打开一次文件并保持两种操作的重定向到位?
查尔斯·达菲
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.