使用sed替换shell脚本中的特殊字符

时间:2013-12-06 11:08:37

标签: shell sed sh

我正在尝试编写一个shell脚本,它将替换我使用sed选择的任何字符/字符串。我的第一次尝试使用特殊字符除外。我一直在尝试使用sed修复特殊字符,以便搜索或替换它们。我决定简化用于测试目的的脚本,并且只处理一个违规角色。但是,我仍然遇到问题。

编辑过的脚本

#! /bin/sh
oldString=$1
newString=$2
file=$3

oldStringFixed=$(echo "$oldString" | sed 's/\\/\\\\/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\[/\\\[/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\]/\\\]/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\^/\\\^/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\*/\\\*/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\+/\\\+/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\./\\\./g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\$/\\\$/g')
oldStringFixed=$(echo "$oldStringFixed" | sed 's/\-/\\\-/g')

sed -e "s/$oldStringFixed/$newString/g" "$file" > newfile.updated
mv newfile.updated "$file"#! /bin/sh

如果不清楚,我试图通过oldString搜索[字符,并用转义版本替换它并将结果分配给oldStringFixed(我需要反引号吗?)。底部两行是我原始脚本的略微修改版本,我相信它可以正常工作。

当我回显固定字符串时,不显示任何内容,并且sed输出错误

sed: can't read [: No such file or directory

任何人都可以解释我的第一个sed线有什么问题吗?

编辑:

感谢Jite,脚本运行得更好。但是,我仍然遇到用空格替换单引号字符的问题,即'*'。新版本在上面。

4 个答案:

答案 0 :(得分:3)

我建议进行两项改进:

  1. 不要像以前那样堆叠对sed的呼叫,而是将所有这些呼叫打包在一个功能中,如下面的escape_string

  2. 您可以为sed替换命令使用精美分隔符,以避免与/相关联的问题成为所涉及字符串的一部分。

  3. 通过这些更改,您的脚本如下所示:

    #! /bin/sh
    oldString="$1"
    newString="$2"
    file="$3"
    
    escape_string()
    {
       printf '%s' "$1" | sed -e 's/[][\\^*+.$-]/\\\1/g'
    }
    
    fancyDelim=$(printf '\001')
    
    oldStringFixed=$(escape_string "$oldString")
    sed -e "s$fancyDelim$oldStringFixed$fancyDelim$newString${fancyDelim}g" "$file" \
      > newfile.updated
    mv newfile.updated "$file"
    

答案 1 :(得分:1)

变化:

oldStringFixed= `sed 's/\[/\[/g' "$oldString"\`

为:

oldStringFixed=$(echo "$oldString" | sed 's/\[/\\\[/g')

问题1:=之后的空格,在分配shell变量时不允许。

问题2:sed期望文件作为输入,而不是字符串。你可以像我的解决方案一样管道它。

问题3:您需要首先转义反斜杠\\,然后您需要转义您的共享\[,共计\\\[:)

旁注:我将``改为$(),因为后者是推荐的实践(由于嵌套,另一个主题)。

答案 2 :(得分:0)

对我而言,这只是一个噩梦,试图让sed为一般情况做这件事。我放弃并编写了一个简短的Python代码来替换sed:

#!/usr/bin/python
# replace.py
import sys

# Replace string in a file (in place)
match=sys.argv[1]
replace=sys.argv[2]
filename=sys.argv[3]

print "Replacing strings in",filename

with open(filename,"r") as f:
  data = f.read().replace(match,replace)

with open(filename,"w") as f:
  f.write(data)

然后可以使用:

#!/bin/bash
orig='<somethinghorrible>'
out='<replacement>'
python replace.py "$orig" "$out" myfile.txt

答案 3 :(得分:0)

替换包含特殊字符的值,请尝试使用带有<|> sed的而不是“ /”

例如:sed -i's |'$ original_value'|'$ new_value'| g'

其中,其中original_value =“ comprising_special_char_ /” new_value =“ comprising_new_special_char:”