仅当变量具有值时才使用sed bash替换

时间:2014-08-29 14:35:30

标签: bash shell sed

我试图找到一种方法,使用变量和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"如果我什么都不给你新的,什么都不做"?


我为过度思考,坏习惯而道歉。基本上我想要完成的是csv文件的第3行是否有值 - 用$ Change inline替换$ Text。如果该行为空,请将$ Text保留为$ Text。

3 个答案:

答案 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)

在启动$Changegrep之前测试sed是否具有值无疑是最有效的bash解决方案,尽管我对{{{}的重复持怀疑态度1}}和grep;如果文件不包含目标字符串,它会保存一个临时文件,但如果文件中包含目标字符串,则会以额外扫描为代价。

如果您正在寻找打字效率,那么以下内容可能很有趣:

sed

将以递归方式查找名称以扩展名find . -name '*.txt' -exec sed -i "s|$Text|${Change:-&}|" {} \; 结尾的所有文件,并在每个文件上执行.txt命令。 sed表示" ${Change:-&}的值(如果它存在且非空),否则为& &#34 ;; &安培;替换$Change sed命令意味着匹配的文本",因此s会将s|foo|&|的每次出现替换为自身。这是一个昂贵的无操作,但如果你的时间比你的cpu时间更重要,那可能是值得的。