从括号中提取字符串

71

我在bash方面还比较新,所以这是一个非常初级的问题。

假设我有一个字符串:

string1 [string2] string3 string4
我想从方括号中提取string2,但是这些方括号可能在任何其他时间包围任何其他字符串。 如何使用sed等工具来实现?谢谢!
9个回答

105

试试这个:

echo $str | cut -d "[" -f2 | cut -d "]" -f1

7
为了确保我理解这里正在发生什么(我对shell脚本很菜),第一个 cut 保存了左括号 [ 右侧的所有内容,第二个保存了右括号 ] 左侧的所有内容;这两个命令结合在一起给了我想要的字符串。 - Dang Khoa

85

以下是使用 awk 的一种方法:

echo "string1 [string2] string3 string4" | awk -F'[][]' '{print $2}'

这个sed选项也可以工作:

echo "string1 [string2] string3 string4" | sed 's/.*\[\([^]]*\)\].*/\1/g'

以下是sed命令的详细说明:

s/          <-- this means it should perform a substitution
.*          <-- this means match zero or more characters
\[          <-- this means match a literal [ character
\(          <-- this starts saving the pattern for later use
[^]]*       <-- this means match any character that is not a [ character
                the outer [ and ] signify that this is a character class
                having the ^ character as the first character in the class means "not"
\)          <-- this closes the saving of the pattern match for later use
\]          <-- this means match a literal ] character
.*          <-- this means match zero or more characters
/\1         <-- this means replace everything matched with the first saved pattern
                (the match between "\(" and "\)" )
/g          <-- this means the substitution is global (all occurrences on the line)

这肯定是有效的,但你能否解释一下发生了什么? - Dang Khoa
4
好的。我会在答案中加入解释。 - Daniel Haley
1
@strictlyrude27 - 我也添加了一个使用 awk 的示例。在我看来,它与接受的答案类似,但更加简洁。 - Daniel Haley
为什么我们需要转义匹配字符串子串的括号?此外,我认为字符类中的闭合方括号必须被转义,但是没有转义也可以工作!我无法理解这一点。 - appanponn

24

在纯 Bash 中:

STR="string1 [string2] string3 string4"
STR=${STR#*[}
STR=${STR%]*}
echo $STR

1
通过使用这个 shell 操作方法能否获取 [string2](还要提取括号)? - Sopalajo de Arrierez
是的。要获取括号内(包括括号)的内容,请执行以下操作:STR="[${STR#[}", 这将删除括号之前的所有内容,然后STR="${STR%]}]",它会删除括号之后的所有内容。变量扩展将删除括号,因此您需要在引号内添加一个括号。 - xizdaqrian

23

使用-F '[分隔符]'指定awk多个分隔符。

如果分隔符是方括号,将它们挨在一起写,像这样][

awk -F '[][]' '{print $2}'

否则你将不得不对它们进行转义

awk -F '[\\[\\]]' '{print $2}'

获取括号内的值的其他示例:

echo "string1 (string2) string3" | awk -F '[()]' '{print $2}'
echo "string1 {string2} string3" | awk -F '[{}]' '{print $2}'

19

这里有另一个解决方案,但它可以处理多个出现的情况,例如:

$ echo "string1 [string2] string3 [string4 string5]" | awk -vRS="]" -vFS="[" '{print $2}'
string2
string4 string5

这里的简单逻辑是:你需要以 "]" 为分隔符进行切割,然后在切割后的单词中找到一个 "[", 再以 "[" 为分隔符进行切割以获取第一个字段。在Python中实现如下:

for item in "string1 [string2] string3 [string4 string5]".split("]"):
    if "[" in item:
       print item.split("]")[-1]

2

这里有一个awk的例子,但我是在匹配括号上进行的,这也更加明显地说明了-F的工作原理。

echo 'test (lskdjf)' | awk -F'[()]' '{print $2}'


2

另一个 awk

$ echo "string1 [string2] string3 [string4]" |
awk -v RS=[ -v FS=] 'NR>1{print $1}' 
string2
string4

1
Read file in which the delimiter is square brackets:
$ cat file
123;abc[202];124
125;abc[203];124
127;abc[204];124

To print the value present within the brackets:
$ awk -F '[][]' '{print $2}' file
202
203
204

一开始看到上述命令中使用的分隔符可能会让人感到困惑。其实很简单,这种情况下需要使用两个分隔符:一个是 [ ,另一个是 ] 。由于分隔符本身是方括号,因此需要将其放置在方括号内部,这一点在第一次使用时看起来有些棘手。
注意:如果方括号是分隔符,则必须按照这种方式放置,即先放 ] ,然后再放 [ 。如果像 -F '[[]]' 这样使用分隔符,则会产生完全不同的解释。
请参考此链接:http://www.theunixschool.com/2012/07/awk-10-examples-to-read-files-with.html

谢谢。你有没有想过如何获取最外层分隔符之间的文本?因此,如果字符串是 x = (b + (c - d)),那么它应该提取出 b + (c - d)。谢谢。 - gbe

0

内联解决方案可能是:

a="first \"Foo1\" and second \"Foo2\""
echo ${a#*\"} | { read b; echo ${b%%\"*}; }

你可以在单行中进行测试:

a="first \"Foo1\" and second \"Foo2\""; echo ${a#*\"} | { read b; echo ${b%%\"*}; }

输出:Foo1

带括号的示例:

a="first [Foo1] and second [Foo2]"
echo ${a#*[} | { read b; echo ${b%%]*}; }

一行代码实现:

a="first [Foo1] and second [Foo2]"; echo ${a#*[} | { read b; echo ${b%%]*}; }

输出:Foo1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接