0

Replace new line \n and upcoming + sign with space

input file

ABC

+ DEF



foo

+ bar

Output should be

ABC   DEF


foo  bar
  • Is your input really exactly like this? With the asterisks? – Panki Feb 12 at 11:54
  • 1
    Does the input contain blank lines, as shown here? – Kusalananda Feb 12 at 12:00
  • 3
    To show your input and output you should use code formatting instead of citation. It is important to see where you have blank lines or spaces. Is there a blank line in the output between ABC DEF and foo bar because there was a blank line in the input? Clarify the details in your question. – Bodo Feb 12 at 12:00
  • 3
    In addition to clarifying what you want, you should also show what you've already tried or researched. See How to Ask. – Anthony Geoghegan Feb 12 at 12:14
4

If the file contains only an alternating pattern with lines starting with a + on every second line, as in

ABC
+ DEF
foo1
+ bar1
foo2
+ bar2

Then use

$ sed 'N;s/\n+  */ /' file
ABC DEF
foo1 bar1
foo2 bar2

This simply reads a line and appends the next line (with N). It then replaces the newline inserted by N, the plus sign, and the spaces following it, with a single space.


Assuming that the file may look like the following, without blank lines (a blank line would be treated as a line without a +). The first line may not start with a plus sign, but the last line is assumed to start with a plus sign.

ABC
+ DEF
foo1
+ bar1
+ baz1
foo2
+ bar2

Then the following sed script would transform it into

ABC DEF
foo1 bar1 baz1
foo2 bar2

The script:

# This is the first line
1 {
    h;      # Save the line in the hold space.
    d;      # Delete and start next cycle.
}

# This line starts with a plus sign and at least one space.
/^+  */ {
    s///;   # Delete the plus sign and the space(s).
    H;      # Append to hold space with embedded newline.
    $ !d;   # Delete and start next cycle (except for on the last line).
}

# This line of input starts a new set of lines.
# Output accumulated line.
x;          # Swap with hold space.
y/\n/ /;    # Replace all embedded newlines with spaces
            # (implicit print)

You would use this as

sed -f script.sed file

As a "one-liner":

sed -e '1{h;d;}' -e '/^+  */{s///;H;$!d;}' -e 'x;y/\n/ /' file
  • Yes , it works good , but it certainly takes some time for large file , Thanks for giving the solution – MTX Feb 13 at 6:30
  • @MTX Well, you did not mention the size of the file nor answer any of the question asking for clarification. – Kusalananda Feb 13 at 6:38
  • i am sorry for my inexperience in asking the the question . I will update the question tomorrow , but your answer really works well . Thanks – MTX Feb 13 at 9:23
3

With Perl you could just slurp the whole file in, and replace the <newline><plus><space> sequences directly:

$ cat foo.txt
ABC
+ DEF
foo1
+ bar1
+ baz1
foo2
+ bar2
$ perl -0777 -pe 's/\n\+ ?/ /g' < foo.txt
ABC DEF
foo1 bar1 baz1
foo2 bar2

(the regex above removes a single optional space after the plus)

  • Yes , it works good , and its too fast for large files too , Thanks for giving the solution – MTX Feb 13 at 6:30
3

With gawk or mawk, which support using a string or regular expression for RS, everything is much simpler:

$ awk -vRS='\n[+]' -vORS= 1

or if you want it to skip multiple empty lines, as in OP's example:

$ awk -vRS='\n+[+]' -vORS= 1 OPs_file
ABC DEF



foo bar

This won't load the more than one line in memory, and won't care if the first line starts with a +.

1

Using GNU sed we may load two lines in the pattern space and examine the state of boundary where the two meet.

In case, we see first line follows the 2nd starting with a + or the 2nd is an empty line, we change the boundary to a blank. Then go back and read and append the next line into the pattern space. Perform same checks n actions. Upon fail of the above criteria, we print the first line only remove it from pattern space, and go back read the next line and append into pattern space. Rinse nd repeat.

 $ sed -E '
      :loop
         $!N
         s/\n(\+|$)/ /
      tloop
      P;D
   ' input.txt 

 ABC   DEF   
 foo   bar
0

I have done by below command Tried not to use any command which mentioned above

Method 1

sed '/^$/d' filename|sed "s/[^A-Za-z]//g"|perl -pne "s/\n/ /g"| awk '{print $1,$2"\n"$3,$4}'

output
ABC DEF
foo bar

Second method

step1:

    p=`cat y.txt| sed '/^$/d'| sed "s/[^A-Za-z]//g"| awk '{print NR}'| sort -rn| sed -n '1p'`


step2:

    for ((i=1;i<=$p;i++)); do cat y.txt| sed '/^$/d'|sed -n ''$i'{p;n;p}'| sed "N;s/\n/ /g";i=$(($i+1)); done| sed "s/[^a-zA-Z]/ /g"


output
ABC   DEF
foo   bar

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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