I have a data in a file as {{1,department}}.

I need to capture the values as given below:


I tried awk command for data with single {}, it worked. but for double {{}} the command is not working.

the command i used is:

`var1=`echo $line | awk -F '[{}]' '{print $2}' | awk -F '[,]' '{print $1}'
$ echo "{{1,department}}" | awk -F "{{|}}|," '{print $3}'

$ echo "{{1,department}}" | awk -F "{{|}}|," '{print $2}'
  • can u explain it pls.. – akr Aug 1 '18 at 6:25
  • 1
    we have three seperators. 1. {{ 2.}} 3. ,(comma). based upon that, we are printing the values. so {{ is taken as one separator. – Kamaraj Aug 1 '18 at 6:37

With GNU grep and any POSIX shell:

out=$(grep -Po '\{\{\K.*?(?=\}\})' < your-file)
  • -P: tells grep to use perl compatible regular expressions for it's \K and (?=) operators
  • \K: sets the start of the returned value. a\Kb matches on ab but returns b. So here, we match on {{... but only return ... to exclude {{ from the output.
  • (?=...) achieves the same thing for }}. It's a look-ahead operator that matches with 0 width if ... matches there without ... being included in the returned value
  • so $out ends up with 1,department. We use the ${var%%pattern} and ${var#pattern} standard shell operators to extract the part before and after the first comma.

That assumes the file contains only one {{...}} occurrence and that it contains at least one comma.

POSIXly, you can replace that grep command with:

sed -n 's/.*{{\([^}]*\)}}.*/\1/p'

Now if you have

some text {{1,department}} other text

in a shell variable, you can also extract it with:

  • zsh

    if [[ $string =~ '\{\{([^},]*),([^}]*)\}\}' ]]; then
      val1=$match[1] val2=$match[2]
  • bash

    if [[ $string =~ \{\{([^},]*),([^}]*)\}\} ]]; then
      val1=${BASH_REMATCH[1]} val2=${BASH_REMATCH[2]}
  • can u explain me this.. also i m having line in a variable.. not in a file. say $line. How will i use command for same – akr Aug 1 '18 at 6:13
  • i have the file with many {{}} with each occurring on different line. So i m reading each line in a loop as $ line and processing each further. So how to use the same command on a variable – akr Aug 1 '18 at 6:24

You can print the values (with a leading space) with:

$ echo "{{1,department}}" | awk -F '[ {},]' 'NF=NF'
 1 department

That will allow to read the values:

read val1 val2 <<<$(echo "{{1,department}}" | awk -F '[ {},]' 'NF=NF')

This will work for one bracket and any additional fields:

$ echo "{{1,department,name,list}}" | awk -F '[ {},]' 'NF=NF'
 1 department name list

A similar solution is possible with grep:

$ echo '{1,department}' | grep -Po '(?<={|,)[^{,}]*(?=,|})'

$ echo '{{1,department}}' | grep -Po '(?<={|,)[^{,}]*(?=,|})'

$ echo '{{1,department,name,list}}' | grep -Po '(?<={|,)[^{,}]*(?=,|})'

From a variable in the shell it needs to match the exact number of fields:

$ value='{{1,department}}'
$ re='\{\{([^},]*),([^}]*)\}\}'
$ [[ $value =~ $re ]] && echo "${BASH_REMATCH[@]:1}"
1 department

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.