我需要通过搜索模式对文件执行替换,并通过执行另一个命令来获取替换,该命令提供要替换的字符串。但是,还需要对目录中的每个文件执行此操作。以下语法不起作用,因为sed没有输入文件。
find . type f -exec sed -i "s/<pattern1>/$(sed -n 's/abcd\(pattern2\)efgh/\1/p')/g" {} \;
这个想法是外部sed的内部sed返回pattern2用作pattern1的替代品。但是我需要在目录中的每个文件上执行此操作。我无法弄清楚语法。
如果我使用find for inside sed,
find . type f -exec sed -i "s/<pattern1>/$(find . -type f -exec sed -n 's/abcd\(pattern2\)efgh/\1/p' {} \;)/g" {} \;
我以错误结束 sed:-e expression#1,char 53:unterminated's'命令。
我可以帮忙解决这个问题吗?
答案 0 :(得分:3)
如果您假设每个找到的文件都包含abcd\(pattern2\)efgh
的单匹配,并且您想从那里取出pattern2
并将其用作在同一个文件中替换pattern1
,就像用户未知的原始答案一样。这是重新粉刷特定自行车棚的尝试。
find . -type f -exec sh -c 'for f; do
sed -n "s%abcd\\(pattern2\\)efgh%s/<pattern1>/\\1/g%p" "$f" |
sed -i -f - "$f"; done' _ {} +
这里可以突出一些事情。
sed
替换中使用不同的分隔符,因此我们可以明确地嵌套它们。
%
或/
,显然请选择另一个分隔符。sed
脚本周围使用doube引号。这意味着所有的反斜杠必须加倍,以防止它们被吃掉#34;用双引号。find
结果传递给简单的sh -c
脚本。
find ... -exec sh -c 'sed -n "s%foo%s/moo/bar/%p" "$1" | sed -i -f - "$1"' _ {} \;
sed -f -
说从标准输入读取脚本。这不便携。
/dev/stdin
代替-
。sed
只是拒绝从标准输入中读取脚本。使用临时文件或其他一些解决方法。答案 1 :(得分:2)
如果有疑问,请牺牲简洁性以便于阅读。这是一个特殊的脚本,ad-hoc.sh(在评论和聊天中讨论之后):
#!/bin/bash
file="$1"
patternInner=$(sed -n -r "s/.*class\s*(.*)\s*:\s*public.*/\1/p" "$file")
if [[ -n "$patternInner" ]]
then
echo -e "$patternInner matching in $file" >> findsed.log
# sed -i "s/void\s*\(test.*\)\s*()/MWTEST($patternInner, \1)/" "$file"
sed "s/void\s*\(test.*\)\s*()/MWTEST($patternInner, \1)/" "$file"
else
echo patternInner empty for file $file >&2
fi
修改:来自现实生活的sed表达。测试非空patternInner。
完成某种日志记录,如果找到模式,文件名,匹配的模式。
别忘了chmod a+x ad-hoc.sh
。
如果测试看起来有效,则必须使用sed -i而不是没有-i的行激活该行,以使更改不仅发生在屏幕上,而且发生在文件中。
用法:
for f in *.?pp # would work for a flat directory as well as find.
do
./ad-hoc.sh "$f"
done 2> forsed.err
或发现,如果你坚持:
find . -type f -name "*.?pp" -exec ./ad-hoc.sh {} ";" 2> findsed.err
当然它可以放在单引号中并用
执行... -exec bash -c '....(ad-hoc.sh
code
here)' {} ";"
但在这种情况下我更喜欢ad-hoc脚本。少掩盖麻烦。更好的可编辑,更好的可测试性。
根据$ patternInner的可变性,必须考虑掩蔽,但我希望它可能只是字符和数字,没有美元,星号和反斜杠。