我试图找到一种方法,使用变量和sed使用更改的输入文件进行特定的文本替换,但前提是有一个值来替换现有的字符串。没有值=什么都不做(而不是删除现有的字符串)。
实施例 Substitute.csv包含5行=
this-has-text
this-has-text
this-has-text
this-has-text
和file.text有一个句子=
"When trying this I want to be sure that text-this-has is left alone."
如果我在shell脚本中运行以下命令
Text='text-this-has'
Change=`sed -n '3p' substitute.csv`
grep -rl $Text /home/username/file.txt | xargs sed -i "s|$Text|$Change|"
我最终得到了
"When trying this I want to be sure that is left alone."
但我希望保持
"When trying this I want to be sure that text-this-has is left alone."
任何方式告诉sed"如果我什么都不给你新的,什么都不做"?
答案 0 :(得分:4)
Text='text-this-has'
Change=$(sed -n '3p' substitute.csv)
if [[ -n $Change ]]; then
grep -rl $Text /home/username/file.txt | xargs sed -i "s|$Text|$Change|"
fi
答案 1 :(得分:3)
保持简单并使用awk:
awk -v t="$Text" -v c="$Change" 'c!=""{sub(t,c)} {print}' file
如果您需要就地编辑,只需使用带有-i inplace
的GNU awk。
鉴于您明确的要求,这可能是您真正想要的:
awk -v t="$Text" 'NR==FNR{if (NR==3) c=$0; next} c!=""{sub(t,c)} {print}' Substitute.csv file.txt
答案 2 :(得分:2)
在启动$Change
和grep
之前测试sed
是否具有值无疑是最有效的bash解决方案,尽管我对{{{}的重复持怀疑态度1}}和grep
;如果文件不包含目标字符串,它会保存一个临时文件,但如果文件中包含目标字符串,则会以额外扫描为代价。
如果您正在寻找打字效率,那么以下内容可能很有趣:
sed
将以递归方式查找名称以扩展名find . -name '*.txt' -exec sed -i "s|$Text|${Change:-&}|" {} \;
结尾的所有文件,并在每个文件上执行.txt
命令。 sed
表示" ${Change:-&}
的值(如果它存在且非空),否则为& &#34 ;; &安培;替换$Change
sed
命令意味着匹配的文本",因此s
会将s|foo|&|
的每次出现替换为自身。这是一个昂贵的无操作,但如果你的时间比你的cpu时间更重要,那可能是值得的。