在bash
脚本中,如何sed
写入文件名存储在 bash 变量中的文件?输出重定向不起作用,因为我想就地编辑一个文件,将与正则表达式匹配的行拉到另一个文件中,然后在第一个文件中删除它们。
就像是:
sed -i '/^my regex here$/{;w file2;d;}' file1
...但是file1
和file2
两者实际上都在哪里变量那抓住文件名。 (例如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 中引用变量的更多信息,请参见这里关联