1

I am trying to figure out how to break a string to be on character per line.
I.e ahebhaaa to be:

a h e b h a a a 

I tried:

$ echo ahebhaaa | sed 's/\(.\)\(.\)/\1\n\2/g'
I.e. my intention was "plugin" between chars a new line using capture groups but I get:

a he bh aa a 

I guess this has to do with greedy/non-greedy but adding ?* anywhere in this does not do anything. What am I doing wrong here?

Additionally I found that this:
echo ahebhaaa | sed 's/[^\n]/&\n/g'
Does the job. But I don't understand how it works. What is &? How does the [^\n] work?

3 Answers 3

4

capture groups

Your first example was close, but you're telling sed that you want to take 2 characters at a time with the \(.\)\(.\) bit, to do it using a capture group you could adjust it like so:

$ echo ahebhaaa | sed 's/\(.\)/\1\n/g' a h e b h a a a 

using &

As to why the sed example with the & works. The & in a search and replace is what ever characters the regular expression matched. So everything that was not a \n.

Examples

$ echo "123 abc" | sed 's/[0-9]*/&&/' 123123 abc 

The first & prints the characters that were matched by the pattern ([0-9]*), 123. The second & prints them a second time.

$ echo "123 abc" | sed 's/ab/&&&/' 123 abababc 

The pattern we're looking for is ab. As we walk the string 123 abc sed is printing the non-matched characters, 123. Then the string ab is encountered which at that point matches what we're searching and replacing on. So sed then replaces it with 3 copies of what matched (abbab). Finally sed prints the c.

The notation [^\n] creates a set of not a end of line character. So think of sed as it's walking along your string of text, ahebhaaa, it's testing each of these characters and saying "Is this not a \n"? If it's not a end of line character, then sed does a search and replace on this character and the & prints what was matched, i.e. the character, along with a new line character. It then repeats this as it walks along the ahebhaaa string.

References

3
  • Great explanation!The & is it part of the standard regex?I don't remember using it ever before Commented Sep 15, 2013 at 10:24
  • @Jim - yeah it's a standard part, I haven't seen it used myself that much either. I'll add a reference if you want to read up on it a bit more. Commented Sep 15, 2013 at 10:26
  • @Jim - see updates. Commented Sep 15, 2013 at 10:30
2

I don't understand why the \n comes into play in that example, since it is a single line pattern space situation, so there are no newlines. Therefore this should suffice:

sed 's/./&\n/g' 
0
2

An alternative in Perl

echo "abcdefg"|perl -nle 'print for split//' 
2
  • +1:Can not figure out how to run perl one-liners from a bash like that Commented Sep 15, 2013 at 16:10
  • 1
    @Jim man perlrun will help you with the usage of switches. "Magic" one-liners like the above make heavy use of Perl's special variables. The above statement, when made explicit, reads print $_ foreach $_ (split //,$_) See man perlvar for more on special variables. Commented Sep 15, 2013 at 17:19

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.