Home > Net >  How do I search and replace a string after an arbitrary amount of white space in bash?
How do I search and replace a string after an arbitrary amount of white space in bash?

Time:12-02

I’m using bash shell. I have a text file containing only the line

name           "Test Program"

I would like to add curly braces around the string after name, making the file look like

name           { “Test Program" }

I tried the below expression

perl -pi -e 's/name(\s )"(.*)"/name$1{ "$2" }/g' /tmp/test.txt

But ended up with a file containing only

name           

Am I misunderstanding something about the arbitrary white space (\s) or substituting?

CodePudding user response:

perl -pi -e 's/name(\s )"(.*)"/name$1{ "$2" }/g' /tmp/test.txt

Here, $1{ "$2" } is interpreted as "the $2 key of the %1 hash".

Put braces around the $1 variable to disambiguate the expansion:

perl -pi -e 's/name(\s )"(.*)"/name${1}{ "$2" }/g' /tmp/test.txt
# ..................................^.^

or escape the open brace

perl -pi -e 's/name(\s )"(.*)"/name$1\{ "$2" }/g' /tmp/test.txt
# ...................................^

Or, use the the \K operator

perl -pi e 's/name\s \K(".*")/{ $1 }/' test.txt

CodePudding user response:

Assuming just the one pair of double quotes, and not limited to a perl solution ...

One idea using sed:

sed -E 's/("[^"]*")/{ \1 }/' test.txt

Where:

  • -E - enable extended regex (and capture groups)
  • ("[^"]*") - (capture group) match a " 0-or-more non-" characters "
  • { \1 } - replace the match with { capture group }

This generates:

name           { "Test Program" }

Once satisfied the results are correct you can add the -i flag to have the change made to the source file, eg:

$ cat test.txt
name           "Test Program"

$ sed -Ei 's/("[^"]*")/{ \1 }/' test.txt

$ cat test.txt
name           { "Test Program" }

Assuming we need to verify match for the name string ...

sed -E 's/([[:space:]]*name[[:space:]] )("[^"]*")/\1{ \2 }/' test.txt

Where:

  • ([[:space:]]*name[[:space:]] ) - (1st capture group) is 0-or-more spaces name 1-or-more spaces
  • ("[^"]*") - (2nd capture group) same explanation as before
  • \1{ \2 } - 1st capture group { 2nd capture group }

Sample data file:

$ cat test.txt
name           "Test Program"
  name         "Test Program"
boat           "Test Program"
names          "Test Program"

$ sed -E 's/([[:space:]]*name[[:space:]] )("[^"]*")/\1{ \2 }/' test.txt
name           { "Test Program" }
  name         { "Test Program" }
boat           "Test Program"
names          "Test Program"

CodePudding user response:

Try with sed:

cat test.txt | sed 's/^name[ ]\ /name       { /g' | sed 's/["][ ]*$/" }/g'

CodePudding user response:

You may use this perl command:

perl -i -pe 's/(name\s )("[^"] ")/$1 { $2 }/' file

cat file

name            { "Test Program" }

Or this sed:

sed -i.bak -E 's/(name[[:blank:]] )("[^"] ")/\1 { \2 }/' file
  • Related