linuxsed

The command block in the sed command is malfunctioning and cannot be used properly


"I encountered an issue while learning sed commands. Each part of a sed command block must be on a separate line." such as 123.txt File contents are as follows

line 1
123
line 2
line 3

I'm using the following command in the Linux terminal:

sed '/123/ {i\good}' 123.txt 

but it shows

sed: -e expression #1, char 0: unmatched '{'.

However, when I use

sed '/123/ { i\
good
}' 123.txt 

it runs correctly. I suspect that sed cannot recognize the backslash \ properly within command blocks.

OS rhel8.8 and sed (GNU sed) 4.5

I tried running the command in a script, but it still couldn't recognize the newline escape in the command block. must use as

sed '/123/ { i\
good
}' 123.txt 

The format used in my linux textbook is as follows.

sed '/123/ {i\good}' 123.txt 

I want to know why it can't recognize \. If I write the command without line breaks, how should I write it?"


Solution

  • The reason using ChapGPT is banned here for answers is because

    while the answers which ChatGPT and other generative AI technologies produce have a high rate of being incorrect, they typically look like the answers might be good and the answers are very easy to produce

    Although they may get better in future, for now I suggest only using them in areas where you already have a good idea of what valid answers look like.


    You have various options to specify your sed script.

    use actual newlines

    For maximum portability (and readability, which becomes more important for longer scripts), use actual newlines, as in your working code:

    sed '/123/ { i\
    good
    }' 123.txt 
    

    (sed does accept semi-colons as an alternative to newlines in some situations but that does not help here.)

    use multiple -e

    The POSIX specification for sed states that multiple -e options can be given, where each after the first are treated as if being preceded by a newline:

    sed -e '123/ { i\' -e 'good' -e '}' 123.txt
    

    This works with many sed implementations. Unfortunately not all follow POSIX (e.g. some BSD will fail).

    insert newlines using the shell

    Assuming one has a variable (say nl) that contains a newline, it can be used as:

    sed '123/ { i\'"$nl"'good'"$nl"'}' 123.txt
    

    Note that the variable use is in double-quotes.

    How to get the newline into the variable?

    1. You could just do:
    nl='
    '
    

    but then you might as well just write the sed command with actual newlines.

    1. Some shells provide non-standard $'...' expansion:
    nl=$'\n'
    

    (Or just use directly.)

    1. If IFS has its default value, its third character is a newline but relying on that is a bad idea.

    2. Some versions of printf (e.g. bash) allow storing a string directly into a variable:

    printf -v nl '\n'
    
    1. Standard printf can generate newlines. Unfortunately, an invocation like nl=$(printf '\n') fails because the shell discards trailing newlines on $(...) output! So some trickery is needed. For example:
    nlx=$(printf '\nx')
    nl=${nlx%?}
    

    or

    eval $(printf 'nl="\n"')