我正在尝试使用 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 答案比这个牙签森林更好。