使用sed传输的输出

时间:2018-05-18 14:47:40

标签: unix awk sed

我有一个使用sometext捕获单行的sed命令。它捕获的文件中的行以换行符结束。我试图在管道中使用此变量,但是,当我尝试回显,或者将其与需要输入的其他命令一起使用时,结果为空白。例如: sed '1,1!d' somefile.txt | echo "$1",我知道变量本身并非空,因为我可以用echo "$1"替换cat $1并查看正确的打印输出。

编辑 - 我尝试过管道到tr -d并删除换行符。我已经确认换行符已经消失,但回声仍然显示为空白。猫没有。

编辑2 - 我将变量传送到if语句... | if [[ -z $1 ]]; then cat $1; fi它命中if,确定为空,因此运行cat,它将非空行打印到控制台。如果变量为空,为什么cat仍然打印出信息?

导致这种不一致的原因是什么?如何解决我的问题?最终目标是运行一个sed的输出,通过另一个输出来替换目标文件中的特定行。

sed '1,1!d' somefile.txt | sed '2,1s/.*/'$1'/' targetfile.txt

somefile.txt的内容:

these
are
words

targetfile.txt的内容:

The next line should say these
This line should say these
The previous line should say these

sed后输出回声:

<empty>

sed后猫的输出:

these

第二个sed的输出,使用1st的输入:

The next line should say these

the previous line should say these

2 个答案:

答案 0 :(得分:3)

您对参数和输入数据感到困惑。看看这个:

$ echo "$1"

$ echo "foo" | if [[ -z $1 ]]; then cat $1; fi
foo

我的shell的第一个参数$1为空,因此if [[ -z $1 ]]成功。 cat $1生成输出的原因是您在该语句中有一个基本的shell编程错误 - 您不能引用您的变量$1。正确的语法不是cat $1,而是cat "$1"。看看差异:

$ echo "foo" | if [[ -z $1 ]]; then cat "$1"; fi
cat: '': No such file or directory

我们可以简化代码,使更清楚的事情发生:

$ echo "foo" | cat $1
foo

$ echo "foo" | cat "$1"
cat: '': No such file or directory

echo "foo" | cat $1生成输出的原因是,在调用cat之前,shell将未加引号的$ 1扩展为空,因此该语句仅等同于echo "foo" | cat,所以cat只是副本输入从管道输入到它的输出。

另一方面,echo "foo" | cat "$1"生成错误,因为shell在调用cat之前将"$1"扩展为空字符串,因此它要求cat打开名为{{1的文件那当然不存在,因此错误。

除非您有特定的理由不完全理解所有含义,否则请始终引用您的shell变量。如果您不确定这些含义是什么,请阅读shell手册页和/或谷歌。

你的代码的另一部分:

<null>

但是,与sed '1,1!d' somefile.txt | echo "$1" 不同,cat既不从管道读取输入,也不读取作为参数传递的文件名。 echo的输入只是您提供的字符串参数列表,因此echo将导致cat读取包含echo "foo" | cat的输入流并输出它,foo将不会产生输出,因为{ {1}}不是为了从管道读取输入而设计的,因此它只打印一个空字符串,因为你没有给它任何参数。

我不清楚你真正想要完成的是什么,但我你可能想用echo "foo" | echo的第二行替换echo的第一行{ {1}}。如果是这样的话,那就是:

targetfile.txt

不要尝试使用sed来做这件事,否则你会发现自己在逃避/引用地狱,因为与awk不同,sed不理解文字字符串,请参阅Is it possible to escape regex metacharacters reliably with sed

答案 1 :(得分:0)

您似乎想要从file1中提取第一行,并使用它来替换{​​{1}}中的第二行。

目前,您使用第一个file2从第一个文件中提取该值,但是将其发送到sed上的第二个sed而不是参数{{{ 1}})。

您的描述令人困惑,因此我将其用作stdin

$1

这是file1

File 1 Line 1
File 1 Line 2
File 1 Line 3

有很多方法可以做到这一点。

方法1

file2

我不确定为什么我现在感觉像牙医一样: - )

如果你想把它全部放在一行,就像有些人喜欢做的那样:

File 2 Line 1
File 2 Line 2
File 2 Line 3

方法2

这个有点棘手。它使用第一个# Extract line1 from file1 extracted=$(sed '1!d' file1) # Replace line 2 in file2 with extracted value sed "2s/.*/$extracted/" file2 为第二个x=$(sed '1!d' file1) && sed "2s/.*/$x/" file2 编写脚本:

sed

如果您自己查看第一个sed,您会看到它正在为第二个生成脚本:

sed  's/^/2s|.*|/;s/$/|/;q' file1 | sed -f /dev/stdin file2

如果查看第二个sed,您将看到它正在执行其标准输入上传递的脚本:

sed  's/^/2s|.*|/;s/$/|/;q' file1
2s|.*|File 1 Line 1|

方法3

更容易sed

sed -f /dev/stdin ...

您需要注意的是,我将2个文件传递给awk,而脚本中的awk 'FNR==NR{if(NR==1)saved=$0;next} FNR==2{$0=saved}1' file1 file2 File 2 Line 1 File 1 Line 1 File 2 Line 3 表示awk当前正在处理第一个文件,因为FNR是行当前文件中的数字和NR是到目前为止从所有文件处理的总行数FNR==NR。因此,在处理第二个文件时,NR比第一个文件中的行数大于FNR。