如何使用 sed 写入存储在变量中的文件名?

如何使用 sed 写入存储在变量中的文件名?

bash脚本中,如何sed写入文件名存储在 bash 变量中的文件?输出重定向不起作用,因为我想就地编辑一个文件,将与正则表达式匹配的行拉到另一个文件中,然后在第一个文件中删除它们。

就像是:

sed -i '/^my regex here$/{;w file2;d;}' file1

...但是file1file2两者实际上都在哪里变量抓住文件名。 (例如file2=$(mktemp)。)

所以我真正想要的是文件名的变量扩展,但命令的其余部分没有扩展sed,并将整个内容作为传递给sed命令的单个参数。

无论出于何种原因,以下方法都不起作用:

sed -i '/my regex here/{;w '"$file2"';d;}' $file1

它说“不匹配{”,我不明白为什么。

我有什么办法可以做到这一点吗?

答案1

因为您使用的是单个表达式,所以(包括)sed之后的所有内容都是w}解释为工作文件姓名:

该参数wfile应终止编辑命令。

您可以看到,如果添加第二个命令},例如:

sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1

那么匹配的行将my regex here保存在名为whatever;d;}wherewhatever$file1扩展后的文件中。
正确的语法是通过单独的命令,或者使用多个表达式:

sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2

或每行一个命令:

sed '/my regex here/{
w '"$file1"'
d
}
' $file2

答案2

我找到了答案堆栈溢出在“如何让 sed 'w' 命令知道文件名在哪里结束?”

正如 terdon 指出的那样,问题不在于变量,但它也与大括号无关;尝试一下sed '/^l/w testing;p',您会发现它不会抛出任何错误,而是将以 an 开头的所有行写入l名为testing;p.

问题实际上是文件名后缺少换行符。

所以答案是在 sed 命令中使用内联换行符:

sed -i '/my regex here/{;w '"$file2"'
d;}' $file1

或者,更简洁的是,使用两个单独的-e参数:

sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1

如果您不喜欢两个相邻的引号(您可能很容易忽略它们),只需将 write 命令放在它自己的参数中即可:

sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1

答案3

使用双引号代替单引号来引用 sed 命令。并且不要忘记转义合适的字符。

有关在 bash 中引用变量的更多信息,请参见这里关联

相关内容