Can You Explain This Sed One-Liner

Can you explain this sed one-liner?

This will do the same job as tac, i.e. revert the order of rows.
Rewriting the sed script to pseudocode, it means:

$line_number = 1;
foreach ($input in $input_lines) {
// current input line is in $input
if ($line_number != 1) // 1!
$input = $input + '\n' + $hold; // G

$hold = $input; // h

$line_number++
}

print $input; // $p

As you can see, the sed language is very expressive :-) the 1! and $ are so called addresses, which put conditions when the command should be run. 1! means not on the first row, $ means at the end. Sed has one auxiliary memory register which is called hold space.

For more information type info sed on linux console (this is the best documentation).

-n disables the default print $input command in the loop itself.

The terms pattern space and hold space are equivalents of the variables $input and $hold (respectively) in this example.

Confusing Sed One-Liner in Makefile Tutorial

The sed pattern will be processed by make first, so if the rule that it applies to is trying to build foo.P then $@ will be translated to foo.P and $* to foo. This means that the actual sed command will be something like:

sed 's/\(foo\)\.o[ :]*/\1.o foo.P : /g' < foo.d > foo.P

\(foo\) matches foo exactly and sets the first replacement to what matches (i.e. foo) \. matches a literal dot and [ :]* matches any number of spaces and colons.

As you can see the \1 replacement is a bit redundant as the matched string is fixed. This would have worked just as well.

sed 's/foo\.o[ :]*/foo.o foo.P : /g' < foo.d > foo.P

which could have been made from:

sed 's/$*\.o[ :]*/$*.o $@ : /g' < $*.d > $@

Display one line of two with sed

sed -n 'p;n'

-n suppresses all output that isn't explicitly printed.

'p;n' is the sed script to run on each input line. The semicolon is a separator between two commands, p and n.

p prints the current line, without moving to the next line.

n moves to the next line without printing anything.

Once these two commands have been run on the current line, sed moves on to the next line, and then runs the script again on this new line. This script will keep running until there are no more input lines. The effect of the script is to keep printing, then skipping lines.


p;n;n

This is mostly the same script, but it skips two lines instead of one.


p;p;n

This is mostly the same script, but it prints the line twice before skipping it.


why it isn't printing the first and second line, and hide the third one ?

Because p doesn't advance sed forward a line, only n (or reaching the end of the script) does that.

(It might be helpful to note that sed -n 'p' prints every line without skipping any, sed -n 'p;p;p' prints every line three times, and sed -n 'p;n;p' is equivalent to sed -n 'p'.)

sed one liner to delete replace and merge

I believe this might be what you are after:

sed '/^$/d;:a;/\r\n*$/{N;ba};s/\r\n*//;s/MB//g;s/-/0/g' file

The idea is the following:


  1. read a line in the pattern-space
  2. /^$/d: if the line is empty, delete it and restart the cycle
  3. :a;/\r\n*$/{N;ba};: if the pattern space ends with CR followed by one or more LF, read the next line, append an LF and the line to the pattern-space. Keep on doing that until the pattern space ends with something else.
  4. s/\r\n*//: Delete all CRLF* sequences.
  5. s/MB//g;s/-/0/g : perform final substitutions.

sed, how to replace one line with 2 line?

Try this if you're in bash:

sed -i.bak $'s/You are good/You are good\\\nYou are the best/g' /output.txt

Strange, eh? But seems to work. Maybe sed can't handle the newline correctly so it needs to be escaped with another backslash, thus \\ which will become a single \ before going to sed.

Also, note that you were not passing an extension to -i.


Edit

Just found another solution. As the newline needs to be escaped when passing to sed (otherwise it thinks it's a command terminator) you can actually use single quotes and a return, just insert the backslash before entering the newline.

$ echo test | sed 's/test/line\
> line'
line
line

sed only works on one line

You need to make the whitespace in front of the ip_forward optional, by adding a * after \s.

In your sample input, there is no whitespace character in front of ip_forward, so your expression doesn't match because it is requiring at least the whitespace character.

#!/bin/bash

#Locations
LocationOne="$SERVER_DIR/config.yml"

if [ -f "$LocationOne" ]
then
cd "$SERVER_DIR"
sed -i "s/^.*\s*host:.*/ host: $IP:$PORT/g" $SERVER_DIR/config.yml
sed -i "s/^.*\s*ip_forward: false/ ip_forward: true/g" $SERVER_DIR/config.yml
fi

On a separate note, you're matching .* in front of ip_forward which is any number of any characters (excluding newline), and I'm not sure if that was the intent.

sed one-liner to convert all uppercase to lowercase?

With tr:

# Converts upper to lower case 
$ tr '[:upper:]' '[:lower:]' < input.txt > output.txt

# Converts lower to upper case
$ tr '[:lower:]' '[:upper:]' < input.txt > output.txt

Or, sed on GNU (but not BSD or Mac as they don't support \L or \U):

# Converts upper to lower case
$ sed -e 's/\(.*\)/\L\1/' input.txt > output.txt

# Converts lower to upper case
$ sed -e 's/\(.*\)/\U\1/' input.txt > output.txt

Translating a sed one-liner into awk

$ cat tst.awk
BEGIN {
split("1 AAA 5 EEE 26 ZZZ",tmp)
for (i=1; i in tmp; i+=2) {
dict[tmp[i]] = tmp[i+1]
}
FS="[ =]"
OFS="="
}
$1 == "[PREFIX]" {
print $1
for (i=2; i<NF; i+=2) {
print " " ($i in dict ? dict[$i] : $i), $(i+1)
}
next
}
{ print }

$ awk -f tst.awk file
Normal line
Another normal line
[PREFIX]
AAA=Something
EEE=SomethingElse
ZZZ=42
Normal line again

Convert sed One-Liner to perl

This perl one-liner should work:

perl -pe 's/:\n$/: /' file
Looking into the table etl_f_gl_balance
# of -1 values in etl_f_gl_balance.row_key: 0
# of -1 values in etl_f_gl_balance.ledger_key: 1020
# of -1 values in etl_f_gl_balance.gl_account_key: 1020
# of -1 values in etl_f_gl_balance.legal_entity_key: 1020
# of -1 values in etl_f_gl_balance.cost_center_key: 995
# of -1 values in etl_f_gl_balance.natural_account_key: 1020
# of -1 values in etl_f_gl_balance.posting_period_fiscal_key: 5
# of -1 values in etl_f_gl_balance.posting_period_key: 5


Related Topics



Leave a reply



Submit