How to insert string or newline before a pattern "Using SED" ( Without replacing the pattern) In MAC OS
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.
sam
Updated on July 13, 2022Comments
-
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 bashI 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 over 10 yearsDon't strictly need
-r
for this:sed 's/b\+/\n&/g'
-
fedorqui over 10 yearsUhms, 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 over 10 yearsThere is extra
1
appearing afterbb
in output because of&1
. -
fedorqui over 10 yearsOooops I was doing some tests and forgot to delete it :) Thanks @anubhava!
-
Kevin over 10 yearsDon't bother with
+
, justsed 's/b/\nb/g'
is fine. Those withsed
s that don't take escapes like that, the\n
will have to be a backslash (\
) followed by a literal newline. -
Kevin over 10 yearsFine for
grep
s with-P
, but OSX took that out in 10.8. -
fedorqui over 10 years@sam indicate what error you are receiving, which one of the solutions in my question you tried...
-
sam over 10 yearswhen 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 over 10 years@sam then you can use either
sed 's/\([b]+\)/\n\1/g
orsed 's/b\+/\n&/g'
-
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 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 over 10 yearsWhat if you do not use
-i
? Do you see change in the output? In that case, you can dosed .... file > tmp_file && mv tmp_file file
-
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 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 over 10 yearsThanks @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 over 10 yearsSo your grepv doesn't support grep -P ?
-
Jotne over 10 yearsI do see. But if
awk
is installed (its normal installed) and do a better job, you may have a better tool for you. -
sam over 10 yearsi don't want the users to install awk for me.. thats why no AWK
-
sam over 10 yearsit works fine in terminal... but when i insert it in my bash script its not working...
-
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 over 10 yearsAdded another
awk
version. What system are you on that does not haveawk
?