user3514163
user3514163

Reputation: 61

Merging two lines into one within a file for a specific pattern

I am a novice in shell scripting . I have a input like this

abc
 xyz
cdf
kjd
mno
abc
 xyzjhd
lkds
kmdew
abc
  yzxnh

I need a output which is in form

abcxyz
cdf
kjd
mno
abcxyzjhd
lkds
kmdew
abcyzxnh

Upvotes: 0

Views: 89

Answers (8)

Ed Morton
Ed Morton

Reputation: 203209

sed is an excellent tool for simple substitutions on a single line*, for all other text manipulation the standard UNIX tool is awk. This problem involves doing things across multiple lines (specifically joining 2 lines) and therefore sed should not be considered for a solution and therefore you need an awk solution.

This uses GNU awk to read all lines from the file into a single string and then delete all occurrences of a newline followed by blank chars from that string:

$ awk -v RS='^$' -v ORS= '{gsub(/\n[[:blank:]]+/,"")}1' file
abcxyz
cdf
kjd
mno
abcxyzjhd
lkds
kmdew
abcyzxnh

Note that the above uses the [:blank:] character class which does not include newlines so ALL it will do is append a line that starts with blank chars to the preceding line.

* sed has language constructs for doing things across multiple lines but those constructs became obsolete in the mid-1970s when awk was invented. The only sed language constructs that are still appropriate to use are s, g, and p (with -n). If you need anything else from sed then you are using the wrong tool.

Upvotes: 2

Håkon Hægland
Håkon Hægland

Reputation: 40718

perl -0777 -pe 's/\n\s+//g' file

or if the lines to be joined always starts with abc:

perl -0777 -pe 's/(abc)\s*\n\s+/$1/g' file

Upvotes: 0

potong
potong

Reputation: 58371

This might work for you (GNU sed):

sed '$!N;s/\n  *//;P;D' file

Read the next line and remove the previous newline and any following spaces if there are spaces at the beginning of a line.

If there are likely to be more than one such line, then:

sed ':a;$!N;s/\n  *//;ta;P;D' file

Upvotes: 1

Scrutinizer
Scrutinizer

Reputation: 9926

Another awk

awk 'NR>1{ORS=sub(/^[[:blank:]]+/,x)?x:RS; print p} {p=$0} END{ORS=RS; print p}' file

Upvotes: 1

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed -n '1h;1!H;${x;s/\n //g;p}' YourFile

same idea as @sat but with the whole file in memory and change once using g

Upvotes: 0

fedorqui
fedorqui

Reputation: 289515

This awk makes it:

$ awk '/^ / {gsub(/^[ ]*/, ""); print a$0; a=""; next} {if (a) print a; a=$0}' file
abcxyz
cdf
kjd
mno
abcxyzjhd
lkds
kmdew
abcyzxnh

Explanation

  • /^ / {} on lines starting with space, do {}.
  • {gsub(/^[ ]*/, ""); print a$0; a=""; next} remove all of leading spaces and print the previous line together with current one. Then jump to next line.
  • {if (a) print a; a=$0} otherwise, and if a is set, print the previous line. Also, store the current one in the a variable.

Upvotes: 0

sat
sat

Reputation: 14949

You can try this sed,

sed 'N;/\n .*/{s/\n//; s/ \+//;};P;D' yourfile

OR

sed 'N;/\n .*/{s/\n \+//;};P;D' yourfile

If want in-place edit,

sed -i.bak 'N;/\n .*/{s/\n \+//;};P;D' yourfile

Upvotes: 1

Kent
Kent

Reputation: 195039

gawk:

kent$  awk -v RS="" '{gsub(/\n\s+/,"")}7' file   
abcxyz
cdf
kjd
mno
abcxyzjhd
lkds
kmdew
abcyzxnh

Upvotes: 1

Related Questions