chippycentra
chippycentra

Reputation: 3432

Using sed on line break element

Hello let say I have a file such as :

$OUT some text
some text 
some text
$OUT
$OUT
$OUT

how can I use sed in order to replace the 3 $OUT into "replace-thing" ?

and get

$OUT some text
some text 
some text
replace-thing

Upvotes: 0

Views: 81

Answers (3)

Raymondo Ponte
Raymondo Ponte

Reputation: 81

for this particular task, I recommend to use awk instead. (hope that's an option too)

Update: to replace all 3 $OUT use: (Thanks to @thanasisp and @glenn jackman)

cat input.txt | awk '
BEGIN {
    i = 0
    p = "$OUT" # Pattern to match
    n = 3 # N matches
    r = "replace-thing"
}

$0 == p {
    ++i
    if(i == n){
        print(r)
        i = 0 #reset counter (optional)
    }
}

$0 != p {
    i = 0
    print($0)
}'

If you just want to replace the 3th $OUT usage, use:

cat input.txt | awk '
BEGIN {
    i = 0
    p = "\\$OUT" # Pattern to match
    n = 3 # Nth match
    r = "replace-thing"
}

$0 ~ p {
    ++i
    if(i == n){
        print(r)
    }
}

i <= n || $0 !~ p {
    print($0)
}'

Upvotes: 2

potong
potong

Reputation: 58488

This might work for you (GNU sed):

sed -E ':a;N;s/[^\n]*/&/3;Ta;/^(\$OUT\n?){3}$/d;P;D' file

Gather up 3 lines in the pattern space and if those 3 lines each contain $OUT, delete them. Otherwise, print/delete the first line and repeat.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 247042

With sed:

sed -n '1h; 1!H; ${g; s/\$OUT\n\$OUT\n\$OUT/replace-thing/g; p;}' file

GNU sed does not require the semicolon after p.

With commentary

sed -n '    # without printing every line:
    # next 2 lines read the entire file into memory
    1h      # line 1, store current line in the hold space
    1!H     # not line 1, append a newline and current line to hold space

    # now do the search-and-replace on the file contents
    ${      # on the last line:
        g   # replace pattern space with contents of hold space
        s/\$OUT\n\$OUT\n\$OUT/replace-thing/g   # do replacement
        p   # and print the revised contents
    }
' file

This is the main reason I only use sed for very simple things: once you start using the lesser-used commands, you need extensive commentary to understand the program.

Note the commented version does not work on the BSD-derived sed on MacOS -- the comments break it, but removing them is OK.


In plain bash:

pattern=$'$OUT\n$OUT\n$OUT'      # using ANSI-C quotes
contents=$(< file)
echo "${contents//$pattern/replace-thing}"

And the perl one-liner:

perl -0777 -pe 's/\$OUT(\n\$OUT){2}/replace-thing/g' file

Upvotes: 2

Related Questions