我有一个使用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
these
are
words
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
答案 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。