对 Bash 还很陌生,大约是令人疲惫不堪的一周。到目前为止我很喜欢它并且真的很喜欢长链管。但我注意到的是,如果我需要使用 STDOUT 作为变量,我必须打破管道。
这是一个例子:
echo -e 'Going to the movies can be fun.
When a dog found a cat a trouble began.
Do not text while driving please.' > example
假设我想将第二行中的每个“A”替换为“THE”。这就是我目前的做法。
cat example | head -2 | tail -1 | sed 's/ a / the /g'
这就是我想要的方式
# None of these work
cat example | head -2 | tail -1 | ${xargs//a /the }
cat example | head -2 | tail -1 | ${cat//a /the }
cat example | head -2 | tail -1 | ${$0//a /the }
cat example | head -2 | tail -1 | ${\1//a /the }
现在我必须创建一个变量然后使用 bash 字符串操作。
middle=$(cat example | head -2 | tail -1)
echo ${middle//a /the }
我确实意识到对于这个例子你可以使用很多工具
cat example | awk 'gsub(/ a/," the");'
我真正想弄清楚的是是否有任何方法可以使用管道 STDOUT 作为变量。
答案1
如何将第二行的 a 替换为 the,然后继续管道?
首先修复 来sed
匹配所有a
s、事件作为开始和结束。
sed -r -e 's/(^| )a($| )/\1the\2/g'
然后使其仅在第 2 行匹配
sed -r -e '2 s/(^| )a($| )/\1the\2/g'
现在你可以做
echo -e 'Going to the movies can be fun.
When a dog found a cat a trouble began.
Do not text while driving please.' | sed -r -e '2 s/(^| )a($| )/\1the\2/g' | less
另一种解决方案
首先删除cat
cat
只是打开一个文件并将其传递到其输出,然后通过管道传输到下一个命令。通过使用输入重定向 ( ),我们可以让 shell 打开一个文件并将其定向到下一个(现在是第一个)命令的输入<
。我们可以将其写为command args <input-file
或<input-file command args
。我们将 .txt 文件放在命令中的哪个位置并不重要<input-file
。我将重定向放在第一位,以便可以从左到右读取管道。
< example head -2 | tail -1 | sed 's/ a / the /g'
替代方案(做完全相同的事情):
head -2 <example | tail -1 | sed 's/ a / the /g'
它们的作用与以下相同,但少了一个过程。
cat example | head -2 | tail -1 | sed 's/ a / the /g'
接下来封装:这里我们用括号括住 3 个命令,然后我们可以将所有 3 个命令的输出通过管道传输到另一个命令(这里我使用 less)。
{
< example head -1
< example head -2 | tail -1 | sed 's/ a / the /g'
< example tail -1
} | less
答案2
命令替换是可行的方法(就像使用 一样),但恕我直言,在这些情况下$middle
通过管道传输会更容易。sed
话虽如此:我知道你只是在学习,但结合起来head
几乎tail
没有sed
必要。你的例子可以纯粹地表达sed
为
sed -n '2s/ a / the /gp' example
-n
默认情况下抑制输出2
匹配第二行s/ a / the /g
替换所有 ("g"lobal) 出现的a
.p
打印结果