cygwin 上的 sed 引号和反斜杠

cygwin 上的 sed 引号和反斜杠

我正在尝试使用 cygwin 上的 sed 从字符串中提取子字符串。

#!/bin/bash

var1="foo\ bar"
var2="baz"

var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | sed "s/"$var1"//"`
echo "$var4"

但我得到了以下输出,这是由反斜杠引起的: sed: -e 表达式 #1,字符 6:未终止的“s”命令

我怎样才能编写 sed 命令来输出“baz”?

答案1

问题是 shell 和sed解释反斜杠。您可能能够sed正确地执行此操作,但我建议您使用其他工具,例如 Perl:

#!/bin/bash
export var1="foo\ bar" ## The export allows Perl to access the variable as $ENV{var1}
var2="baz"
var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | perl -ne '$var1=quotemeta($ENV{var1}); s/$var1//; print'`
echo "$var4"

上面的例子使用了 Perl 的quotemeta函数转义所有非 ASCII 字符,使正则表达式能够正确匹配反斜杠。

最后,你为什么要这样做?你真的需要匹配吗?\还是你想匹配 bash 字符串中的空格?如果是这样,有更简单的方法。

答案2

简单来说...sed 不起作用...比如在列上,它更面向行。不要强制命令 - 在合适的地方使用它。Cut 会是一个更好/更简单的选择

或者,如果您正在寻找子字符串提取,那么 awk 也适合......示例

Kaizen ~/so_test
$ echo "foo\ bar baz" | awk '{print substr($0,1,8)}'
+ echo 'foo\ bar baz'
+ awk '{print substr($0,1,8)}'
foo\ bar

在这种情况下使用起来更简单,这样就足够了吗?

答案3

为了使这个命令能用 sed 工作,我们需要转义反斜杠。准备好迎接疯狂吧:

$ echo "$var1"
foo\ bar
$ echo "$var3"
foo\ bar baz
$ echo "$var3" | sed "s/$var1//"
foo\ bar baz
$ echo "${var1//\\/\\\\}"
foo\\ bar
$ echo "$var3" | sed "s/${var1//\\/\\\\}//"
 baz

当然,还有很多其他字符也需要转义,例如*,所以@terdon 的 perl 答案比这个牙签森林更好。

相关内容