How to insert string or newline before a pattern "Using SED" ( Without replacing the pattern) In MAC OS

11,537

Solution 1

With sed:

$ echo "aaaabbaaabbaa" | sed -r 's/([b]+)/\n\1/g'
aaaa
bbaaa
bbaa

sed -r allows to catch blocks with () and print them back with \1. The block it catches it [b]+, meaning "one or more b's", and prints it back preceded by a new line.

As I see you are using sed -i, it is also good to do:

sed -i.bak -r 's/([b]+)/\n\1/g' input.txt

Also, easier (thanks Glenn Jackman!)

$ echo "aaaabbaaabbaa" | sed 's/b\+/\n&/g'
aaaa
bbaaa
bbaa

It replaces all sequences of "b" and replaces that with a newline followed by that same sequence of "b" (& represents whatever was matched on the left side of s///).

Solution 2

grep -oP with lookahead regex will be easier:

echo 'aaaabbaaabbaa' | grep -oP '.+?[^b](?=(b|$))'

aaaa
bbaaa
bbaa

Solution 3

If your input string really does contain only a and b characters, then I think the problem degenerates to a simple replacement of all instances of ab with a<newline>b. If this is the case then you can omit sed altogether and use the Shell Parameter Expansion feature in bash:

At the terminal:

$ str="aaaabbaaabbaa"
$ echo "${str//ab/a
> b}"
aaaa
bbaaa
bbaa
$ 

Or in a shell script:

$ cat ab.sh 
#!/bin/bash
echo "${1//ab/a
b}"
$ ./ab.sh "aaaabbaaabbaa"
aaaa
bbaaa
bbaa
$ 

This works for me on OSX 10.8.5.

This information is also available on the bash manpage hosted by apple.com. Search for "parameter/pattern" on that page.

Solution 4

You could say:

$ echo aaaabbaaabbaa | sed 's/b\{1,\}/\'$'\n&/g'
aaaa
bbaaa
bbaa

or

$ echo aaaabbaaabbaa | sed $'s/b\{1,\}/\\\n&/g'
aaaa
bbaaa
bbaa

In order to make sed interpret the regex as extended regular expressions, you could use the -E option:

$ echo aaaabbaaabbaa | sed -E 's/b+/\'$'\n&/g'
aaaa
bbaaa
bbaa

Solution 5

sed -e 's/bb/\ nn/g' input.txt

I got this to work. It is very similar to your original attempt. I am on an iMac, so I am pretty sure the same will work for you.

Share:
11,537
sam
Author by

sam

Updated on July 13, 2022

Comments

  • sam
    sam almost 2 years

    I have a file with the following content:

    aaaabbaaabbaa
    

    and i need an output like:

    aaaa
    bbaaa
    bbaa
    

    I need a new line to be added before first occurrence of 'b'. I need only SED command to use in bash

    I am using the following command. I know its now the perfect one..

    Can anyone tell me a better command than this. Pl note only SED command i need to use in bash

    sed -i.bak  -e 's/bb/qbb/g' input.txt  
    sed -i.bak  -e 's/qbb/\'$'\nbb/g' input.txt
    
  • glenn jackman
    glenn jackman over 10 years
    Don't strictly need -r for this: sed 's/b\+/\n&/g'
  • fedorqui
    fedorqui over 10 years
    Uhms, so this is good news: when catching just one block we can play with &, no need to \1. I like it, thanks! Updated, also.
  • anubhava
    anubhava over 10 years
    There is extra 1 appearing after bb in output because of &1.
  • fedorqui
    fedorqui over 10 years
    Oooops I was doing some tests and forgot to delete it :) Thanks @anubhava!
  • Kevin
    Kevin over 10 years
    Don't bother with +, just sed 's/b/\nb/g' is fine. Those with seds that don't take escapes like that, the \n will have to be a backslash (\) followed by a literal newline.
  • Kevin
    Kevin over 10 years
    Fine for greps with -P, but OSX took that out in 10.8.
  • fedorqui
    fedorqui over 10 years
    @sam indicate what error you are receiving, which one of the solutions in my question you tried...
  • sam
    sam over 10 years
    when i use sed -r 's/([b]+)/\n\1/g' input.txt sed: illegal option -- r usage: sed script [-Ealn] [-i extension] [file ...] sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
  • fedorqui
    fedorqui over 10 years
    @sam then you can use either sed 's/\([b]+\)/\n\1/g or sed 's/b\+/\n&/g'
  • fedorqui
    fedorqui over 10 years
    @sam What do you mean no change? Be more explicit if you want to be helped. I guess you are getting the result in the screen, right? If you read my answer, adding -i updated the file.
  • sam
    sam over 10 years
    @fedorqui even i tried -i I couldn't see any change in the file...No change means no change in file text..
  • fedorqui
    fedorqui over 10 years
    What if you do not use -i? Do you see change in the output? In that case, you can do sed .... file > tmp_file && mv tmp_file file
  • sam
    sam over 10 years
    @fedorqui $ sed 's/([b]+)/\n\1/g' input.txt > tmp.txt $ sed 's/b\+/\n&/g' input.txt > tmp.txt no change between input and tmp files... $ sed -i 's/b\+/\n&/g' input.txt > tmp.txt and for '-i' sed: 1: "input.txt": command i expects \ followed by text thank you for your patience
  • fedorqui
    fedorqui over 10 years
    @sam as you are on Mac OS and I don't have it to test, you'd better check the other answers.
  • sam
    sam over 10 years
    Thanks @fedorqui kindly up vote it if you feels its a good question.. and none of the answers right... for SED command for this requirement..
  • anubhava
    anubhava over 10 years
    So your grepv doesn't support grep -P ?
  • Jotne
    Jotne over 10 years
    I do see. But if awk is installed (its normal installed) and do a better job, you may have a better tool for you.
  • sam
    sam over 10 years
    i don't want the users to install awk for me.. thats why no AWK
  • sam
    sam over 10 years
    it works fine in terminal... but when i insert it in my bash script its not working...
  • Shruti Singh
    Shruti Singh over 10 years
    @sam: It sound strange. Your terminal is running shell. What you type in terminal is (should be) exactly same as line in shell script. If doesn't, something is really broken.
  • Jotne
    Jotne over 10 years
    Added another awk version. What system are you on that does not have awk?