Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using sed's append/change/insert without a newline

I want to replace my pattern space in SED. I can do this with s/^.*$/hello world/; - but can I do it using the c command somehow - without using line breaks in my sed script? It's not entirely clear to me whether that's possible in any way.

(Same question for the a and i commands)

like image 232
einpoklum Avatar asked Oct 22 '25 15:10

einpoklum


2 Answers

If your shell is bash, here is a convenient way to use c in a one-liner:

$ seq 3 | sed $'/2/c\\\nNew Text'
1
New Text
3

This looks for any line containing 2 and changes it to New Text.

This uses bash's $'...' feature to enter a newline in a string. The newline is represented by \n. The backslash that is needed after the c is represented by \\.

The $'...' feature is also available in ksh93, zsh, mksh, and FreeBSD sh.

like image 160
John1024 Avatar answered Oct 25 '25 14:10

John1024


TLDR

You can't control a,i,r et. al. They print stuff + \n.

Instead, modify the pattern space using s and use P to print pattern space up until, excluding new-line to, for desired result.

Examples

printf 'foo\nfoo' | sed -n 'P' | cat -A
foo$
foo

a/i won't work

printf 'foo\nfoo' | sed -n '
#print pattern-space wo. newline
P
# apppend the char F
aF
' | cat -A
foo$
F$
foo$
F$

I believe it works similar to r/R. It appends after the cycle and always with newline.

But you can always use N with s instead. Ie.

printf 'foo\nfoo' | sed -n -e '
# append \n + nextline wo. its \n to pattern-space
N
' -e '
# replace the 1st \n with bar (append without trailing \n)
s@\n@bar@
' -e '
# print pattern-space up until, excluding \n
P
' | cat -A
foo$
bar$
foo$
bar
printf 'foo\nfoo' | sed -n -e '
# expect last-line, append \n and read next-line
$! {
  N
}
' -e '
# replace \n with bar \n
s@\n@bar\n@
' -e '
# on last line ($), append bar wo. new-line
$ { 
  s@$@bar@
}
' -e '
# print pattern-space in its entirety
p
' | cat -A
foobar$
foobar

Note

  • The examples use cat -A to show newlines in output ($)
  • I use @ as a delimiter for s. This is personal, possibly silly, preference. It can be the standard /,| or þ if you like.
  • I've separated commands using -e 'cmd', including comments, for readability.
    Equavilent one-liner for the last is printf 'foo\nfoo' | sed -n '$!;s@\n@bar\n@;$s@$@bar@;p' | cat -A

🤷‍♂️

Tip

  • Use a script file, preferably in an editor like vim with sed syntax highlighting.
#!/bin/sed -f

# expect last-line, append \n and read next-line
$! {
  N
}
# replace \n with bar \n
s@\n@bar\n@
# on last line ($), append bar wo. new-line
$ { 
  s@$@bar@
}
# print
p

To debug

  • Use l
    print current pattern-space with escaped special characters
  • Use =
    print current line
like image 27
CervEd Avatar answered Oct 25 '25 14:10

CervEd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!