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

问题描述 投票:0回答:7

对于

grep
,有一个固定字符串选项
-F
(
fgrep
) 用于关闭搜索字符串的正则表达式解释。
sed
有类似的设施吗?我在这个人身上找不到任何东西。推荐另一个 gnu/linux 工具也可以。

我使用

sed
进行查找和替换功能:
sed -i "s/abc/def/g"

unix sed
7个回答
11
投票

必须使用

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
二进制文件并不总是可用。


6
投票

选项 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

4
投票

如果您不想想逃离字符串,您可以通过两步达到您的目标:

  1. fgrep
    要替换的行(获取行号),以及
  2. 然后使用
    sed
    替换此行。

例如

#/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
投票

如果你不反对 Ruby 或长线,你可以使用这个:

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

replace test3.txt abc def

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


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

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

您仍然需要“转义”

'
字符,但其余的应该是直接的。

注意:这首先是对如何将特殊字符串传递给 sed 因此是

$_REQUEST['old']
字符串的回答,但是这个问题的表述更为恰当。


-5
投票

您应该使用

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.
© www.soinside.com 2019 - 2024. All rights reserved.