bash 如何将特定分隔符之间的文本捕获到 shell 变量中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/693460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I capture the text between specific delimiters into a shell variable?
提问by lhunath
I have little problem with specifying my variable. I have a file with normal text and somewhere in it there are brackets [ ](only 1 pair of brackets in whole file), and some text between them. I need to capture the text within these brackets in a shell (bash) variable. How can I do that, please?
我在指定我的变量时没有什么问题。我有一个带有普通文本的文件,其中某处有括号[ ](整个文件中只有一对括号),它们之间有一些文本。我需要在 shell (bash) 变量中捕获这些括号内的文本。请问我该怎么做?
回答by strager
Bash/sed:
重击/sed:
VARIABLE=$(tr -d '\n' filename | sed -n -e '/\[[^]]/s/^[^[]*\[\([^]]*\)].*$//p')
If that is unreadable, here's a bit of an explanation:
如果这是不可读的,这里有一些解释:
VARIABLE=`subexpression` Assigns the variable VARIABLE to the output of the subexpression.
tr -d '\n' filename Reads filename, deletes newline characters, and prints the result to sed's input
sed -n -e 'command' Executes the sed command without printing any lines
/\[[^]]/ Execute the command only on lines which contain [some text]
s/ Substitute
^[^[]* Match any non-[ text
\[ Match [
\([^]]*\) Match any non-] text into group 1
] Match ]
.*$ Match any text
// Replaces the line with group 1
p Prints the line
回答by lhunath
May I point out that while most of the suggested solutions might work, there is absolutely no reasonwhy you should fork another shell, and spawn several processes to do such a simple task.
我可以指出,虽然大多数建议的解决方案可能有效,但绝对没有理由您应该派生另一个 shell,并生成多个进程来完成如此简单的任务。
The shell provides you with all the tools you need:
shell 为您提供了您需要的所有工具:
$ var='foo[bar] pinch'
$ var=${var#*[}; var=${var%%]*}
$ echo "$var"
bar
回答by Zsolt Botykai
Sed is not necessary:
sed 不是必需的:
var=`egrep -o '\[.*\]' FILENAME | tr -d ][`
But it's only works with single line matches.
但它仅适用于单行匹配。
回答by Zsolt Botykai
Using Bash builtin regex matching seems like yet another way of doing it:
使用 Bash 内置正则表达式匹配似乎是另一种方式:
var='foo[bar] pinch'
[[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]] # Bash 3.0
var="${BASH_REMATCH[1]}"
echo "$var"
回答by Jonathan Leffler
What about:
关于什么:
shell_variable=$(sed -ne '/\[/,/\]/{s/^.*\[//;s/\].*//;p;}' $file)
Worked for me on Solaris 10 under Korn shell; should work with Bash too. Replace '$(...)' with back-ticks in Bourne shell.
在 Korn shell 下的 Solaris 10 上对我来说有效;也应该与 Bash 一起使用。$(...)在 Bourne shell 中用反引号替换 ' '。
Edit: worked when given [ on one line and ] on another. For the single line case as well, use:
编辑:当在一行给出 [ 而 ] 在另一行时工作。对于单行情况,请使用:
shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
-e '/\[.*\]/s/^.*\[\([^]]*\)\].*$//p' $file)
The first '-e' deals with the multi-line spread; the second '-e' deals with the single-line case. The first '-e' says:
第一个 ' -e' 处理多行价差;第二个 ' -e' 处理单行情况。第一个 ' -e' 说:
- From the line containing an open bracket
[not followed by a close bracket]on the same line - Until the line containing close bracket
], - substitute anything up to and including the open bracket with an empty string,
- substitute anything from the close bracket onwards with an empty string, and
- print the result
- 从包含开放括号的行开始,在同一行上
[没有紧跟右括号] - 直到包含右括号的行
], - 用空字符串替换包括左括号在内的任何内容,
- 用空字符串替换右括号以后的任何内容,并且
- 打印结果
The second '-e' says:
第二个 ' -e' 说:
- For any line containing both open bracket and close bracket
- Substitute the pattern consisting of 'characters up to and including open bracket', 'characters up to but excluding close bracket' (and remember this), 'stuff from close bracket onwards' with the remembered characters in the middle, and
- print the result
- 对于包含左括号和右括号的任何行
- 用中间记住的字符替换由“最多包含开括号的字符”、“最多但不包括闭括号的字符”(并记住这一点)、“从闭括号开始的内容”组成的模式,以及
- 打印结果
For the multi-line case:
对于多行情况:
$ file=xxx
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa
bbbbbbb
cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
-e '/\[.*\]/s/^.*\[\([^]]*\)\].*$//p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$
And for the single-line case:
对于单行情况:
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa bbbbbbb cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
-e '/\[.*\]/s/^.*\[\([^]]*\)\].*$//p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$
Somewhere about here, it becomes simpler to do the whole job in Perl, slurping the file and editing the result string in two multi-line substitute operations.
在这里的某个地方,在 Perl 中完成整个工作变得更简单,在两个多行替换操作中处理文件和编辑结果字符串。
回答by jfs
Assuming you are asking about bash variable:
假设您正在询问 bash 变量:
$ export YOUR_VAR=$(perl -ne'print if /\[(.*?)\]/' your_file.txt)
The above works if brackets are on the same line.
如果括号在同一行,则上述方法有效。
回答by John Ellinwood
var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*//' infile.txt`
回答by John Ellinwood
Thanks to everyone, i used Strager's version and works perfectly, thanks alot once again...
感谢大家,我使用了 Strager 的版本并且运行良好,再次非常感谢......
var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*//' infile.txt`
回答by John Ellinwood
Backslashes (BSL) got munched up ... :
反斜杠(BSL)被吃掉了......:
var='foo[bar] pinch'
[[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]] # Bash 3.0
# Just in case ...:
[[ "$var" =~ [^BSL]BSL[]*BSL[([^BSL[]*)BSL].* ]] # Bash 3.0
var="${BASH_REMATCH[1]}"
echo "$var"
回答by cb0
2 simple steps to extract the text.
2个简单的步骤来提取文本。
- split var at [ and get the right part
- split var at ] and get the left part
- 在 [ 处拆分 var 并获得正确的部分
- 在 ] 处拆分 var 并获取左侧部分
cb0$ var='foo[bar] pinch' cb0$ var=${var#*[} cb0$ var=${var%]*} && echo $var bar
cb0$ var='foo[bar] pinch' cb0$ var=${var#*[} cb0$ var=${var%]*} && echo $var bar

