Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何将特定分隔符之间的文本捕获到shell变量中?_Bash_Unix_Variables - Fatal编程技术网

Bash 如何将特定分隔符之间的文本捕获到shell变量中?

Bash 如何将特定分隔符之间的文本捕获到shell变量中?,bash,unix,variables,Bash,Unix,Variables,我在指定变量方面没有什么问题。我有一个包含普通文本的文件,文件中的某个地方有括号[](整个文件中只有一对括号),它们之间有一些文本。我需要在shell(bash)变量中捕获这些括号内的文本。请问我该怎么做?Bash/sed: VARIABLE=$(tr -d '\n' filename | sed -n -e '/\[[^]]/s/^[^[]*\[\([^]]*\)].*$/\1/p') 如果这是不可读的,这里有一点解释: VARIABLE=`subexpression` Assig

我在指定变量方面没有什么问题。我有一个包含普通文本的文件,文件中的某个地方有括号
[]
(整个文件中只有一对括号),它们之间有一些文本。我需要在shell(bash)变量中捕获这些括号内的文本。请问我该怎么做?

Bash/sed:

VARIABLE=$(tr -d '\n' filename | sed -n -e '/\[[^]]/s/^[^[]*\[\([^]]*\)].*$/\1/p')
如果这是不可读的,这里有一点解释:

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
/\1/                 Replaces the line with group 1
p                    Prints the line
那么:

shell_variable=$(sed -ne '/\[/,/\]/{s/^.*\[//;s/\].*//;p;}' $file)
在Korn shell的Solaris 10上为我工作;也应该与Bash一起使用。将Bourne shell中的“
$(…)
”替换为反勾号

编辑:在[一行上]和[另一行上]给定时工作。对于单线情况,也可使用:

shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                        -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
第一个“
-e
”处理多线排列;第二个“
-e
”处理单线情况。第一个“
-e
”表示:

  • 在同一行中,包含一个开括号的行
    [
    后面不跟一个闭括号的行
    ]
  • 直到包含右括号的行
    ]
  • 用空字符串替换开放括号内的任何内容
  • 用空字符串替换从右括号开始的任何内容,以及
  • 打印结果
第二个“
-e
”表示:

  • 对于包含开放式括号和封闭式括号的任何行
  • 取代了由“字符到打开括号”、“字符最多但不包括紧括号”(并记住这一点)、“中间括号内的字符”和“中间字符”和
  • 组成的模式。
  • 打印结果
对于多行情况:

$ file=xxx
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa
bbbbbbb
cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa bbbbbbb cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$
对于单线情况:

$ file=xxx
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa
bbbbbbb
cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$
$ cat xxx
sdsajdlajsdl
asdajsdkjsaldjsal
sdasdsad [aaaa bbbbbbb cccc] asdjsalkdjsaldjlsaj
asdjsalkdjlksjdlaj
asdasjdlkjsaldja
$
$ shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \
                          -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file)
$ echo $shell_variable
aaaa bbbbbbb cccc
$

在这里的某个地方,用Perl完成整个工作变得更为简单,在两个多行替换操作中对文件进行slurp处理并编辑结果字符串。

假设您询问的是bash变量:

$ export YOUR_VAR=$(perl -ne'print $1 if /\[(.*?)\]/' your_file.txt)

如果括号在同一行上,上述方法也能起作用。

感谢大家,我使用了Strager的版本,效果非常好,再次感谢大家

var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt`
var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt`
Sed是不必要的:

var=`egrep -o '\[.*\]' FILENAME | tr -d ][`

但它只适用于单线匹配

请允许我指出,虽然大多数建议的解决方案都可能有效,但绝对没有理由让您派生另一个shell,并生成多个进程来完成如此简单的任务

shell为您提供了所需的所有工具:

$ var='foo[bar] pinch'
$ var=${var#*[}; var=${var%%]*}
$ echo "$var"
bar
  • 见:

使用Bash内置正则表达式匹配似乎是另一种方法:

var='foo[bar] pinch'
[[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]]   # Bash 3.0
var="${BASH_REMATCH[1]}"
echo "$var"
反斜杠(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" 
提取文本的2个简单步骤

  • 将var拆分为[并获得正确的部分
  • 在]处拆分变量并获取左侧部分

  • 你是说一个shell变量吗?你在用Bash吗?忘了提,是的,在离我很近的Bash中-你忘了带文件名@莱夫勒,噢,谢谢!我在测试中得到了它,但在解决方案中遗漏了它;我已经有了一个解决方案[在一条线路上]和另一条线路上。如何组合这两个工作?@乔纳森:在Perl中它是微不足道的(它也适用于多个非重叠括号):Perl - 0777 Ne'Perfices 1美元//[(.*])/GS’in FIL.TXTT请考虑使用$()而不是``。它与POSIX兼容,并且更易于阅读和消除歧义。一旦超过某一点,Perl就会比sed更容易。如果要问为什么在给出这些信息的情况下,Strager的版本没有被选为“答案”,这是不合理的吗?是否可以将这三行改为四行?即,是否可以使用此方法从两端剥离,而无需再次分配$var?