Bash while 循环搜索并使用 sed 替换

Bash while 循环搜索并使用 sed 替换

我的以下脚本有问题(这是它的相关部分):

#!/bin/bash

OLD=(
"_MAIN1_"
"_MAIN2_"
)

NEW=(
"#111"
"#222"
)

length=${#OLD[*]}

i=0

while (( i < length ))
do
  sed -e "s/${OLD[$i]}/${NEW[$i]}/g" oldfile.txt > newfile.txt

  #sed -e 's/_MAIN1_/#111/g' oldfile.txt > newfile.txt  # this works

  # Another way that does not work
  #sed -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt > newfile.txt

  ((i++))
done

exit 0

我的目标是替换文件中的字符串并将其保存到新文件中。 “旧”和“新”字符串存储在数组中。

我尝试了很多方法并使用单引号和双引号 - 但没有任何效果。当我echo输入变量时,我在循环内得到了正确的字符串。如果在命令中明确设置了两个字符串,则sed它可以正常工作。

字符串模式遵循我的示例数组中的模式(“new”包含下划线“_”,“old”包含主题标签“#”)。

我在 Ubuntu 16.04 机器上运行 bash。

非常感谢!

答案1

创建一个sed执行所有替换的脚本,然后将该sed脚本应用到您的文件。

for (( i=0; i<${#OLD[@]}; ++i )); do
        printf 's/%s/%s/g\n' "${OLD[$i]}" "${NEW[$i]}"
done >script.sed

sed -f script.sed inputfile >outputfile && mv outptufile inputfile && rm script.sed

通过这种方式,您可以将需要解析输入文件的次数限制为一次。

对于给定的数据OLDNEW脚本sed将生成为

s/_MAIN1_/#111/g
s/_MAIN2_/#222/g

答案2

您的整个脚本(不起作用)可以用一行替换:

sed 's/_MAIN\([12]\)_/#\1\1\1/g' oldfile.txt > newfile.txt

或者,更易读但等效:

sed 's/_MAIN1_/#111/g;s/_MAIN2_/#222/g' oldfile.txt > newfile.txt

还有几十种其他方法可以实现此目的,具体取决于您的情况实际的用例(例如,数据来自哪里、值的实际情况、您尝试对数据执行什么操作等)。

答案3

谢谢拉克什·夏尔马的评论我可以通过使用-ised 命令中的标志来解决这个问题。在循环之前备份原始文件:

cp oldfile.txt oldfile.backup
while (( i < length ))
do
  sed -i -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt
  ((i++))
done

下次我将使用 Perl 进行字符串操作。

编辑:添加((i++))以防止无限循环(感谢善行难陀的评论)。

相关内容