简体   繁体   中英

Escaping quotation marks in a variable with sed

I have a sed command in my script that prints data between specific parts of the text passed to the command as variables:

sed -n "$PART1|,|$PART2|p" file.txt

Everything is fine until I try a part of the text containing a double qoute. For instance, PART1 = of the Rings" and PART2 = Sauron .

I've tried changing the syntax to

sed -n '$PART1|,|$PART2|p' file.txt

However, it didn't like it at all.

Is there any way to automatically escape double quotes passed to sed with variables? Also, it is not possible to change the double quotes in the source file.

Thank you for any suggestions.

Using sed

Let's start with this test file:

$ cat file
something
of the Rings"
keep this text
Dark Lord Sauron
something else

Let's define your variables:

$ part1='of the Rings"'
$ part2=Sauron

Now, let's run sed:

$ sed -n "/$part1/,/$part2/p" file
of the Rings"
keep this text
Dark Lord Sauron

If you really prefer the pipe symbols in place of / :

$ sed -n "\|$part1|,\|$part2|p" file
of the Rings"
keep this text
Dark Lord Sauron

A concern when doing this is that part1 and part2 become part of the sed command and, if maliciously constructed, could do damage to your files. For this case, it is safer to use awk.

Using awk

$ awk -v p="$part1" -v q="$part2" '$0~p,$0~q' file
of the Rings"
keep this text
Dark Lord Sauron

Never enclose scripts in double quotes, always single, to avoid unexpected shell interactions and never use all upper case names for non-exported variables by convention and to avoid clashes with builtin variables. Borrowing @John1024's sample input file:

$ cat file
something
of the Rings"
keep this text
Dark Lord Sauron
something else

$ sed -n '/'"$part1"'/,/'"$part2"'/p' file
of the Rings"
keep this text
Dark Lord Sauron

but more robustly and extensibly you should use an awk script like this:

$ awk -v part1="$part1" -v part2="$part2" '$0~part1{f=1} f; $0~part2{f=0}' file
of the Rings"
keep this text
Dark Lord Sauron

and do not use range expressions. For example to not print the whole range of lines is a trivial tweak with the flag approach:

$ awk -v part1="$part1" -v part2="$part2" 'f; $0~part1{f=1} $0~part2{f=0}' file
keep this text
Dark Lord Sauron

$ awk -v part1="$part1" -v part2="$part2" '$0~part1{f=1} $0~part2{f=0} f' file
of the Rings"
keep this text

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