简体   繁体   中英

Bash: Find a pattern and replace what follows

I have a .txt file that looks like this:

HelloWorld    (3,4,5)
FooFooFoo     {34,34,34}{23,1,2}
BarFooHello   {{4,5,12}}
BarBar        Bar
HelloFoo      {{6,5}}  

I want to find the string 'BarFooHello' on the file and replace whatever is in between the starting string '{{' that directly follows 'BarFooHello' and the ending string '}}' by '12,12,12,12'. The goal is to obtain a file this file at the end:

HelloWorld    (3,4,5)
FooFooFoo     {34,34,34}{23,1,2}
BarFooHello   {{12,12,12,12}}
BarBar        Bar
HelloFoo      {{6,5}}  

How can I do this in Bash? I would love to just have a function in bash that takes 1) the starting string 2) the ending string, 3) the string after which the modification should be performed and 4) the string to put in place of the current stuff that exist in between the starting string and the ending string.

$ sed '/^BarFooHello/ s/{{.*}}/{{12,12,12,12}}/' file.txt
HelloWorld    (3,4,5)
FooFooFoo     {34,34,34}{23,1,2}
BarFooHello   {{12,12,12,12}}
BarBar        Bar
HelloFoo      {{6,5}}  

How it works

sed loops over every line in the file.

  • /^BarFooHello/

    This selects only lines that begin with BarFooHello .

  • s/{{.*}}/{{12,12,12,12}}/

    On those selected lines, this substitutes everything between the first {{ and the last }} on that line and replaces it with {{12,12,12,12}} .

Using sed, you could have :

funct ()
{
start=$1  # "BarFooHello"
begin=$2  # "{{"
end=$3    # "}}"
string=$4 # "12,12,12,12"
file=$5   # The file to perform the replacement

sed "s/^$start   $begin[[:print:]]*$end/$start   $begin$string$end/g"  $file # Sensitive to 3 spaces
# or
sed "s/^$start\(\ *\)$begin[[:print:]]*$end/$start\1$begin$string$end/g"  $file  # Preserve the amount of spaces
}

and used like that :

funct "BarFooHello" "{{" "}}" "12,12,12,12" test.txt

Pure Bash:

#!/bin/bash

repl () {
    line="$1"
    str="$2"
    pre="$3"
    suf="$4"
    values="$5"

    if [[ $line =~ ^$str ]]; then
      line="${line/%$pre*$suf/$pre$values$suf}"
    fi
    echo "$line"
}

while read line; do
   repl "$line" BarFooHello "{{" "}}" 12,12,12,12
done < file

The repl() function works on one line of text at a time, and replaces only if the line matches the string.

Bash has no mechanism for back-references, which necessitates redundancy. ${line/%$pre*$suf/$pre$values$suf} replaces everything from the prefix string through the suffix with the prefix string, new values and suffix string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM