有没有在shell脚本中接受没有分隔符的特殊字符的方法?

时间:2013-12-01 14:59:55

标签: linux shell sh

我的任务是创建一个shell脚本,交换2个字符串,然后输出一个文件。这些命令类似于:

  

sed s / search_for / 替换 / g output.txt> TEMP.DAT

     

mv temp.dat output.txt

脚本的工作原理如下:

./myScript var_A var_B output.file 

我必须工作得很好。第二部分做同样的事情,但我必须将以下特殊字符视为常规字符串:

[ ] ^ * + . $ \ -

我对如何解决这个问题有一个大概的想法(这可能是错误的方式)。我想接受这些字符,并将它们设置为变量,并在前面添加\。

var_A=\\$1
var_B=\\$2

我的问题是*(星号)和\(反斜杠)字符。我正在使用一个简单的测试脚本来查看我可以轻松转换为变量的参数:

for i in "$@"
do
    echo "$i"
done

但* char显示目录中的所有文件,\显示下一个参数。我知道设置-o noglob 设置-f ,但这些对我不起作用(并且不适用于脚本)。我也知道你可以使用反斜杠逃脱,但我也不能使用它。我必须能够使用特殊字符(甚至*和/)并转换为字符串。我希望这一切都有道理,有人可以帮助我。

3 个答案:

答案 0 :(得分:1)

如果我理解正确,你将模式放在变量中,然后在sed中使用这些变量,你需要将模式视为文字字符串,而不是它们在正则表达式中的特殊含义吗?

如果是这样,那么在将模式传递给sed之前,您需要转义特殊符号。这是我的测试的可能实现:

#!/bin/sh

escaped() {
    echo "$1" | sed -e 's/[].+-[$\\^*]/\\&/g'
}

set -- [ ] ^ \* + . \$ \\ -
for pat1; do
    pat2=$(escaped "$pat1")
    echo "$pat1 was $pat1" | sed -e s/$pat2/_/
done

escaped函数接受参数并在特殊字符前加一个反斜杠。循环演示了以这种方式生成的pat2变量正确匹配输入字符串中的特殊字符。

答案 1 :(得分:0)

如果要执行文字替换,sed是错误的工具。

请参阅http://mywiki.wooledge.org/BashFAQ/021中给出的awk脚本。引用这里:

# usage: gsub_literal STR REP
# replaces all instances of STR with REP. reads from stdin and writes to stdout.
gsub_literal() {
  [[ $1 ]] || return
  awk -v str="${1//\\/\\\\}" -v rep="${2//\\/\\\\}" '
    BEGIN { len = length(str); }
    {
      out = "";
      while (i = index($0, str)) {
        out = out substr($0, 1, i-1) rep;
        $0 = substr($0, i + len);
      }
      out = out $0;
      print out;
    }
  '
}

......可以用作......

tempfile=$(mktemp "$file.XXXXXX")
gsub_literal "$search" "$rep" \
    <"$file" \
    >"$tempfile" && \
  mv -- "$tempfile" "$file"

绝对包含$search$rep的任何值。

Perl也非常适合这种类型的操作,具有内联替换功能和(与sed不同)能够直接引用其argv数组或环境变量以进行文字搜索或替换值。

答案 2 :(得分:0)

您必须在shell的命令行上引用您的模式。你无法解决这个问题。

Perl正则表达式为您提供了一个“quotemeta”函数,将每个字符视为文字

perl -e '
    $str = q{this is a string with **emphasis**};
    $pattern = q{**emphasis**};
    $repl = "characters";
    $str =~ s/$pattern/$repl/;
    print $str
'
Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE *emphasis**/ at -e line 5.

perl -e '
    $str = q{this is a string with **emphasis**};
    $pattern = q{**emphasis**};
    $repl = "characters";
    $str =~ s/\Q$pattern\E/$repl/;
    #.........^^
    print $str
'
this is a string with characters