简体   繁体   中英

Replace multiple lines using sed in a bash script

I've a file with multiple lines. I'm looking for help to modify only these lines that are matching the regex pattern and then add some text after each result. I use a mac but the bash script will run on linux, I don't know if it is relevant.

ie

someText
StringToSearch:
    | isoCode |

someOthertext
StringToSearch:
    | isoCode |

againSomOtherText
StringToSearch:
    | isoCode |

after matching " StringToSearch: " I need to add " | uk | " after each " | isoCode | " so the result will be something like:

someText
StringToSearch:
    | isoCode |
    | uk |

someOtherText
StringToSearch:
    | isoCode |
    | uk |

againSomeOtherText
StringToSearch:
    | isoCode |
    | uk |

My regex is ^\s*StringToSearch:\n[^\n]+ and a full working example is available at regex101 following the link

I can't figure out how to implement it in bash using sed.

Actually my sed looks like this: sed -E 's,\^\s*StringToSearch:\n\([^\n]+\),| uk |,' < inputFile sed -E 's,\^\s*StringToSearch:\n\([^\n]+\),| uk |,' < inputFile

$ awk '1; p~/StringToSearch/ && /isoCode/{print "    | uk |"} {p=$0}' ip.txt
someText
StringToSearch:
    | isoCode |
    | uk |

someOthertext
StringToSearch:
    | isoCode |
    | uk |

againSomOtherText
StringToSearch:
    | isoCode |
    | uk |
  • 1 idiomatic way to print contents of $0 which contains current record
  • {p=$0} saves the current record in p variable
  • p~/StringToSearch/ && /isoCode/ this checks if previous line contains StringToSearch and current line contains isoCode
    • if the condition is satisfied, print " | uk |" will add the new content you need

As far as I know, this should work on all versions of awk . So mac/linux will not affect you.


If you insist on sed , you can use

sed '/StringToSearch/{N; s/$/\n    | uk |/}' ip.txt

which I tested on GNU sed and not sure if syntax/feature varies with other implementations. N command will add next line of input to current pattern space. s/$/\n | uk |/ s/$/\n | uk |/ will add the new content after the two lines. sed by default prints pattern space when -n option is not used.

sed -E 's,\^\s*StringToSearch:\n\([^\n]+\),| uk |,'
  • \(...\) saves backreference in regular regex epressions. In extended regex use (...) . Also you do not use anywhere the backreference.
  • \n - sed parses one line at a time . So it can't match \n , unless you append multiple lines to pattern space with N commands.
  • \^ is strange - it matches a ^ character. There is no such character in your text...

You can match easily multi-line with GNU sed by using -z option. Note that it will load the whole file into sed s memory, so it will be memory consuming. Then write a proper regex that will globally match your expression.

Also not to remove replaced string, use & to re-restore it. Then suffix it with the string you want to add.

The commmand:

$ sed -z -E 's,\nStringToSearch:\n[^\n]+\n,&    | uk |\n,g' <<EOF
someText
StringToSearch:
    | isoCode |

someOthertext
StringToSearch:
    | isoCode |

againSomOtherText
StringToSearch:
    | isoCode |
EOF

outputs:

someText
StringToSearch:
    | isoCode |
    | uk |

someOthertext
StringToSearch:
    | isoCode |
    | uk |

againSomOtherText
StringToSearch:
    | isoCode |
    | uk |

Use sed :

sed -e '/^[[:space:]]*StringToSearch:/{' -e n -e n -e 'i\
\ \ \ \ | uk |' -e '}' file > outputfile

Output:

someText
StringToSearch:
    | isoCode |
    | uk |

someOthertext
StringToSearch:
    | isoCode |
    | uk |

againSomOtherText
StringToSearch:
    | isoCode |
    | uk |

This will match any line with optional whitespace and StringToSearch: , then -en -en will read two lines and clear pattern space, then -e 'i\ \ \ \ \ | uk | -e 'i\ \ \ \ \ | uk | will insert a line of your choice, and -e '}' will close the block.

This might work for you (GNU sed):

sed '/StringToSearch/{n;p;s/[^| ]\+/uk/}' file

Match on a line containing StringToSearch .

Print that line and fetch the next.

Print that line and substitute uk for the isoCode (this line will also be printed as part of the normal sed flow).

See here for demo.

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