How can I grab text between specific delimiters into a shell variable?

I have few problems specifying my variable. I have a file with normal text and somewhere in it there are brackets [ ] (just one pair of brackets in the whole file) and some text between them. I need to commit the text in these brackets in a shell variable (bash). How can I do this, please?

+6
variables unix bash
source share
10 answers

Bash / SED:

 VARIABLE=$(tr -d '\n' filename | sed -n -e '/\[[^]]/s/^[^[]*\[\([^]]*\)].*$/\1/p') 

If this is unreadable, here is a little 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 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 
+9
source share

May I point out that although most of the proposed solutions can work, there is absolutely no reason why you should remake another shell and create several processes to perform such a simple task.

In the shell you will find all the necessary tools:

 $ var='foo[bar] pinch' $ var=${var#*[}; var=${var%%]*} $ echo "$var" bar 
+6
source share

Sed is not required:

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

But it only works with single-line matches.

+3
source share

Using the Bash builtin regex combination seems like another way to do this:

 var='foo[bar] pinch' [[ "$var" =~ [^\]\[]*\[([^\[]*)\].* ]] # Bash 3.0 var="${BASH_REMATCH[1]}" echo "$var" 
+2
source share

What about:

 shell_variable=$(sed -ne '/\[/,/\]/{s/^.*\[//;s/\].*//;p;}' $file) 

Worked for me on Solaris 10 under the Korn shell; should also work with bash. Replace ' $(...) ' with back ticks in the Bourne shell.

Edit: worked when given [on one line and] on another. For a single line case, use:

 shell_variable=$(sed -n -e '/\[[^]]*$/,/\]/{s/^.*\[//;s/\].*//;p;}' \ -e '/\[.*\]/s/^.*\[\([^]]*\)\].*$/\1/p' $file) 

The first " -e " refers to multi-line distribution; the second " -e " deals with a single-line case. The first " -e " says:

  • From a line containing an open parenthesis [ followed by no closing bracket ] in the same line
  • As long as the string containing the closed bracket ] ,
  • replace everything before and including the open bracket with an empty string,
  • replace any of the closing brackets with an empty string and
  • print the result

The second " -e " says:

  • For any line containing both open and closed brackets
  • Replace the pattern consisting of “characters before and including the open bracket”, “characters before, but excluding the closed bracket” (and keep this in mind), “material from the closed bracket forward” with catchy characters in the middle and
  • print the result

For 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/^.*\[\([^]]*\)\].*$/\1/p' $file) $ echo $shell_variable aaaa bbbbbbb cccc $ 

And for a single line case:

 $ 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 $ 

Somewhere here, simplifying all of Perl’s work, cutting out a file, and editing the resulting string in two multi-line replace operations.

+1
source share

Assuming you are asking about a bash variable:

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

The above works if the brackets are on the same line.

+1
source share
 var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt` 
0
source share

Thanks to everyone, I used the version of Strager and it works great, thanks again ...

 var=`grep -e '\[.*\]' test.txt | sed -e 's/.*\[\(.*\)\].*/\1/' infile.txt` 
0
source share

Backslashes (BSL) got munched up ...:

 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" 
0
source share

2 easy steps to extract text.

  • split var at [and get the right part
  • split var at] and get the left side
 cb0$ var='foo[bar] pinch' cb0$ var=${var#*[} cb0$ var=${var%]*} && echo $var bar 
0
source share

All Articles