3

I have a file on my Ubuntu machine where I've marked the start of some lines using '@':

@A
bbb
@B
bbb
@D
ccc

I want to remove the new lines at the end of lines starting '@' so the above file becomes

@Abbb
@Bbbb
@Dccc

I can match the lines starting @ using sed:

sed /^@/ ...

but I'm lost at trying to find the way to remove the new line character at the end of the string. There must be a way of doing this easily using sed without having to manually open the file in a text editor and remove them myself.

2
  • 1
    What operating system are you using? We need to know this so we can know what tools, and what implementations of tools, you have available.
    – terdon
    Oct 4 at 14:11
  • Ubuntu 18.04.5 LTS, GNU sed
    – user36196
    Oct 4 at 14:21
5
$ printf '%s\n' 'g/^@/j' ',p' 'Q' | ed -s file
@Abbb
@Bbbb
@Dccc

The above uses a short ed script to join each line in the file that matches the regular expression ^@ with the line after. It then prints all the lines in the editing buffer and quits without saving.


$ sed '/^@/ { N; s/\n//; }' file
@Abbb
@Bbbb
@Dccc

This sed command appends the next line to the input buffer if the current line matches ^@. The inserted newline character is removed and the line printed.

Both of these variations would miss a line starting with @ if it was immediately preceded by such a line. This means, they would turn

@1
@2
X
@3
Y

into

@1@2
X
@3Y

rather than

@1@2X
@3Y

It is unclear whether this is ok or not.

1
  • The lines are broken due to faulty copy-paste from a MacOS terminal window to a (remote) Ubuntu 18.04 window hence why I added the "@" so I know where the lines are supposed to start
    – user36196
    Oct 4 at 14:22
5

Perl to the rescue!

perl -pe 'chomp if /^@/' -- file
  • -p reads the input line by line and prints each line after processing
  • /^@/ matches the @ at the beginning of a line
  • chomp removes the trailing newline
3

Non-sed

  1. if you know that all the lines alternate @ and non-@, then

    paste -d '' - - < file
    
  2. awk

    awk '{printf "%s%s", $0, (/^@/ ? "" : ORS)}' file
    
3

Here's an option with GNU sed:

$ sed -E 'N;s/\n([^@])/\1/' foo.txt 
@Abbb
@Bbbb
@Dccc

Using the N flag:

N

appends line from the input file to the pattern space.

([^@]) matches the firts character after the newline that is not a @, capturing it and then adding it to the previous line.

If you need to modify the file you have to use the option -i: sed -i..., but make a backup first.

0
2

With perl:

$ perl -pe 's/^(@.*)\n/\1/' file
@Abbb
@Bbbb
@Dccc

or

$ perl -pe 's/\n// if /^@/' file
@Abbb
@Bbbb
@Dccc
0
1
awk '{ printf "%s", (/^@/?(NR>1?ORS:""):"")$0 } END{ print "" }' infile

Sample input:

iiii
@A
bbb
xyz
@B
bbb
@D
ccc

Output:

iiii
@Abbbxyz
@Bbbb
@Dccc

Not the answer you're looking for? Browse other questions tagged or ask your own question.