使用sed解释为固定字符串/文字而不是正则表达式

时间:2010-11-09 11:45:49

标签: unix sed

对于grep,有一个固定字符串选项-Ffgrep)来关闭搜索字符串的正则表达式解释。 sed是否有类似的设施?我在这个男人身上找不到任何东西。另一个gnu / linux工具的建议也没问题。

我正在使用sed来查找和替换功能:sed -i "s/abc/def/g"

7 个答案:

答案 0 :(得分:7)

你必须使用sed吗?如果您正在编写bash脚本,则可以执行

#!/bin/bash
pattern='abc'
replace='def'
file=/path/to/file
tmpfile="${TMPDIR:-/tmp}/$( basename "$file" ).$$"
while read -r line
do
  echo "${line//$pattern/$replace}"
done < "$file" > "$tmpfile" && mv "$tmpfile" "$file"

使用较旧的Bourne shell(例如ksh88或POSIX sh),您可能没有那么酷的${var/pattern/replace}结构,但您确实拥有${var#pattern}${var%pattern},可以使用将字符串拆分然后重新组装。如果你需要这样做,你需要更多的代码 - 但它确实不是太糟糕。

如果你已经不在shell脚本中,你可以很容易地制作模式,替换和文件名参数,然后调用它。 :)

PS - $ {TMPDIR: - / tmp}结构使用$ TMPDIR(如果在您的环境中设置),或者如果未设置变量则使用/ tmp。我喜欢将当前进程的pid粘贴到文件名的末尾,希望它稍微有点独特。您可能应该在“真实世界”中使用mktemp或类似的东西,但这可以用于快速示例,并且mktemp二进制文件并不总是可用。

答案 1 :(得分:5)

选项1)转义正则表达式字符。例如。 sed 's/\$0\.0/0/g'会将所有出现的$ 0.0替换为0。

选项2)将perl -p -e与quotemeta结合使用。例如。 perl -p -e 's/\\./,/gi'会将所有.替换为,

您可以在以下脚本中使用选项2:

SEARCH="C++"
REPLACE="C#"
cat $FILELIST | perl -p -e "s/\\Q$SEARCH\\E/$REPLACE/g" > $NEWLIST

答案 2 :(得分:2)

如果你不反对Ruby或长队,你可以使用它:

alias replace='ruby -e "File.write(ARGV[0], File.read(ARGV[0]).gsub(ARGV[1], ARGV[2]))"'

replace test3.txt abc def

这会将整个文件加载到内存中,执行替换并将其保存回磁盘。应该不应该用于大量文件。

答案 3 :(得分:2)

如果你想逃避你的字符串,
您可以通过两个步骤实现目标:

fgrep要替换的线(获得亚麻布),
然后使用sed替换此行。

e.g。

#/bin/sh
PATTERN='foo*[)*abc'    # we need it literal
LINENUMBER="$( fgrep -n "$PATTERN" "$FILE" | cut -d':' -f1 )"

NEWSTRING='my new string'
sed -i "${LINENUMBER}s/.*/$NEWSTRING/" "$FILE"

答案 4 :(得分:0)

您应该使用replace代替sed

从手册页:

   The replace utility program changes strings in place in files or on the
   standard input.

   Invoke replace in one of the following ways:

       shell> replace from to [from to] ... -- file_name [file_name] ...
       shell> replace from to [from to] ... < file_name

   from represents a string to look for and to represents its replacement.
   There can be one or more pairs of strings.

答案 5 :(得分:0)

如果可以将整个文件读入内存,则可以用两行bash代码执行此操作。这是非常灵活的-模式和替换可以包含换行符,以在需要时跨行匹配。它还保留了任何结尾的换行符或缺少的换行符,而使用read的简单循环则不会。

mapfile -d '' < file
printf '%s' "${MAPFILE//"$pat"/"$rep"}" > file

为了完整起见,如果文件可以包含空字节(\0),我们需要扩展上面的内容,它将变成

mapfile -d '' < <(cat file; printf '\0')
last=${MAPFILE[-1]}; unset "MAPFILE[-1]"
printf '%s\0' "${MAPFILE[@]//"$pat"/"$rep"}" > file
printf '%s' "${last//"$pat"/"$rep"}" >> file

答案 6 :(得分:0)

perl -i.orig -pse  'while (($i = index($_,$s)) >= 0) { substr($_,$i,length($s), $r)}'--\ 
     -s='$_REQUEST['\'old\'']' -r='$_REQUEST['\'new\'']' sample.txt
  • -i.orig带有备份的就地修改。
  • 默认情况下,
  • -p从输入文件中打印行
  • -s启用命令行参数的基本解析
  • -e运行此脚本
  • index($_,$s)搜索$s字符串
  • substr($_,$i,length($s), $r)替换字符串
  • while (($i = index($_,$s)) >= 0)重复直到
  • -- perl参数的结尾
  • -s='$_REQUEST['\'old\'']'-r='$_REQUEST['\'new\'']'-设置$s$r

您仍然需要“转义” '个字符,但其余字符应简单明了。

注意:这开始是对How to pass special character string to sed的回答,因此是$_REQUEST['old']字符串,但是这个问题的表达方式更为恰当。