Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `sed` without piping multiple times

Tags:

sed

Example:

echo one two three | sed 's/ /\n/g' | sed 's/^/:/g'

output:

:one
:two
:three

Without piping:

echo one two three | sed 's/ /\n/g;s/^/:/g'

output:

:one
two
three

seems like first pattern isn't expanded before executing second one, but I really don't know much about sed

How can I use first example without piping twice?

PS Pattern used in examples is informative

like image 727
theta Avatar asked Dec 16 '22 06:12

theta


2 Answers

The other way to do it is with repeated -e options:

echo one two three | sed -e 's/ /\n:/g' -e 's/^/:/g'

This is easier to understand when you have many operations to do; you can align the separate operations on separate lines:

echo one two three |
sed -e 's/ /\n:/g' \
    -e 's/^/:/g'

For example, I have a script to generate outline documents from templates. One part of the script contains:

sed -e "s/[:]YEAR:/$(date +%Y)/g" \
    -e "s/[:]TODAY:/$today/" \
    -e "s/[:]BASE:/$BASE/g" \
    -e "s/[:]base:/$base/g" \
    -e "s/[:]FILE:/$FILE/g" \
    -e "s/[:]file:/$file/g" \
    $skeleton |
...

Although it could be done on one line, it would not promote readability.

like image 107
Jonathan Leffler Avatar answered Jan 15 '23 01:01

Jonathan Leffler


The main problem here is that sed decides on what constitutes a line (a pattern that it works on) before executing any commands. That is, if you have only one pattern (one two three), it won't get reinterpreted as multiple lines after execution of s/ /\n/g. If would be still a single pattern, although that would be the one that contains newlines inside it.

The simplest workaround to make sed reinterpret patterns along the newly inserted newlines is just running sed twice, as you did.

Another workaround would be adding something like m option (multi-line buffer) to s command:

$ echo one two three | sed 's/ /\n/g;s/^/:/mg'
:one
:two
:three
like image 37
GreyCat Avatar answered Jan 15 '23 01:01

GreyCat