Unix 使用sed的管道输出

Unix 使用sed的管道输出,unix,awk,sed,Unix,Awk,Sed,我有一个sed命令,它用sometext捕获一行。它捕获的文件中的行以换行符结尾。我试图在管道中使用此变量,但是,当我尝试回显或与需要输入的其他命令一起使用时,结果是空白的。前任: sed'1,1!d'somefile.txt | echo“$1”,我知道变量本身不是空的,因为我可以用cat$1替换echo“$1”,并查看正确的打印输出 编辑-我已尝试将管道连接到tr-d并删除换行符。我已经确认了新行的角色已经消失了,但回声仍然显示为空白。猫不会 edit2-我将变量管道化到if语句…|如果[[

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

编辑-我已尝试将管道连接到tr-d并删除换行符。我已经确认了新行的角色已经消失了,但回声仍然显示为空白。猫不会

edit2-我将变量管道化到if语句
…|如果[[-z$1]];然后是1美元;fi
它点击if,确定为空,因此运行cat,它将向控制台打印一条非空行。如果变量为空,为什么cat仍在打印信息

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

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

somefile.txt的内容: targetfile.txt的内容: sed后的回波输出:

<empty>
these
第二个sed的输出,使用第一个sed的输入:

The next line should say these

the previous line should say these

您似乎想从
file1
中提取第一行,并用它替换
file2
中的第二行

目前,您正在使用第一个
sed
从第一个文件中提取该值,但将其发送到其
stdin
上的第二个
sed
,而不是作为参数(
$1

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

File 1 Line 1
File 1 Line 2
File 1 Line 3
这就是
file2

File 2 Line 1
File 2 Line 2
File 2 Line 3
有很多方法可以做到这一点


方法1

# 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

方法2

这个有点棘手。它使用第一个
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|
如果您查看第二个
sed
,您将看到它正在执行通过其标准输入传递的脚本:


方法3

更简单的是
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

您需要注意的是,我正在将2个文件传递给
awk
,脚本中的
FNR==NR
表示
awk
当前正在处理第一个文件,因为FNR是当前文件中的行号,NR是迄今为止从所有文件处理的行的总数。因此,在处理第二个文件时,NR比FNR大第一个文件中的行数。

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

$ echo "$1"

$ echo "foo" | if [[ -z $1 ]]; then cat $1; fi
foo
我的shell的第一个参数
$1
为空,因此如果[[-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打开一个名为
的文件,而该文件当然不存在,因此产生了错误

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

请写出您代码的另一部分:

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

现在还不清楚您真正想要实现什么,但我认为您可能需要将
targetfile.txt
的第二行替换为
somefile.txt
的第一行。如果是这样,那只是:

awk '
    NR==FNR { if (NR==1) new=$0; next }
    FNR==2  { $0 = new }
    { print }
' somefile.txt targetfile.txt

不要试图使用sed来做这件事,否则你会发现自己在逃避/引用地狱,因为与awk不同,sed不理解文本字符串,请参见。

创建一个可以测试的示例是什么意思?我已经完整地描述了我的过程。在运行我自己的测试时,我从一个包含3行胡言乱语的文件中取了一行。你真的需要我描述一个乱七八糟的测试文件的内容吗?我只是在运行命令
sed'1,1!d'somefile.txt | echo“$1”
sed'1,1!d'somefile.txt | sed'1,1s/*/'$1'/'FileToChange.txt“
sed'1,1!d'somefile.txt | cat$1
其中somefile.txt的内容是\n这些是单词\n(每个单词当然是它自己的一行)如上所述,Cat是唯一一个打印非空行的。我不想听起来很粗鲁,但我刚才所说的一切都在我问的问题中。我不知道在fir之后我应该如何给你输出
$ echo "foo" | cat $1
foo

$ echo "foo" | cat "$1"
cat: '': No such file or directory
sed '1,1!d' somefile.txt | echo "$1"
awk '
    NR==FNR { if (NR==1) new=$0; next }
    FNR==2  { $0 = new }
    { print }
' somefile.txt targetfile.txt