我需要以编程方式替换文件中的某些字符串。作为最低限度的情况,我在这里仅展示|FNAME|
和 的替换|LNAME|
。
目前我正在使用它来完成以下任务:
sed -e "s/|FNAME|/$FNAME/g" -e "s/|LNAME|/$LNAME/g"
问题是某人我的列表会/
在他们的姓名或地址或其他内容中出现。所以我改用@
作为分隔符。你不知道有人@
在他们的姓氏中使用。实际上,一个人的名字中合法地有一个反引号,而他们的名字不是罗伯特。
有什么更强大的方法来执行这个固定字符串的查找替换而不需要选择脆弱的定界符?
答案1
秘诀就是转义变量内容中的任何斜线字符:
fname_esc=${FNAME//\//\\\/}
lname_esc=${LNAME//\//\\\/}
sed -e "s/|FNAME|/$fname_esc/g" -e "s/|LNAME|/$lname_esc/g"
演示:
$ cat file
Hello |FNAME|-|LNAME|
$ FNAME="first/name" LNAME="last/name"
$ fname_esc=${FNAME//\//\\\/}
$ lname_esc=${LNAME//\//\\\/}
$ sed -e "s/|FNAME|/$fname_esc/g" -e "s/|LNAME|/$lname_esc/g" file
Hello first/name-last/name
使用不同的s///g
分隔符可以稍微减轻“倾斜牙签”综合症:
sed -e "s,|FNAME|,${FNAME//,/\\,},g" -e "s,|LNAME|,${LNAME//,/\\,},g"
其他选项:这两个选项都通过命令行选项将替换字符串传递给程序。这样,程序就可以将它们视为纯字符串。但是,这两个选项都使用更高级的正则表达式,因此需要对管道进行转义。
perl
perl -pse 's/\|FNAME\|/$fname/g; s/\|LNAME\|/$lname/g' -- -fname="$FNAME" -lname="$LNAME" file
awk
awk -v fname="$FNAME" -v lname="$LNAME" '{ gsub("\\|FNAME\\|", fname) gsub("\\|LNAME\\|", lname) print }' file