Home > Software design >  Cut-n-paste while preserving last blank line for empty match (awk or sed)
Cut-n-paste while preserving last blank line for empty match (awk or sed)

Time:03-07

I have a two-line "keyword=keyvalue" line pattern (selectively excised from systemd/networkd.conf file):

DNS=0.0.0.0
DNS=

and need the following 2-line answer:

0.0.0.0

But all attempts using sed or awk resulted in omitting the newline if the last line pattern matching resulted in an empty match.

EDIT: Oh, one last thing, this multiline-follow-cut result has to be stored back into a bash variable containing this same 'last blank-line" as well, so this is a two-step operation of preserving last-blank-line

  1. multiline prepending-cut-out before (or save content after) the equal = symbol while preserving a newline ... in case of an empty result (this is the key here). Or possibly jerry-rig a weak fixup to attach a new-line in case of an empty match result at the last line.
  2. save the multi-line result back into a bash variable

sed Approach

When performing cut up to and include that matched character in bash shell, the sed will remove any blank lines having an empty pattern match:

raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"

kvs="$(echo "$rawp"| sed -e '/^[^=]*=/s///')"

echo "result: '${kvs}'"

gives the result:

0.0.0.0

without the corresponding blank line.

awk Approach

Awk has the same problem:

raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"

kvs="$(echo "$rawp"| awk -F '=' -v OFS="" '{$1=""; print}')"

echo "result: '${kvs}'"

gives the same answer (it removed the blank line).

Please Advise

Somehow, I need the following answer:

0.0.0.0

in form of a two-line output containing 0.0.0.0 and a blank line.

Other Observations Made

I also noticed that if I provided a 3-line data as followed (two with a keyvalue and middle one without a keyvalue:

DNS=0.0.0.0
DNS=
DNS=999.999.999.999

Both sed and awk provided the correct answer:

0.0.0.0

999.999.999.999

Weird, uh?

The above regex (both sed and awk) works for:

  • a one-line with its keyvalue,
  • any-line provided that any lines have its non-empty keyvalue, BUT
  • last line MUST have a keyvalue.

Just doesn't work when the last-line has an empty keyvalue.

:-/

CodePudding user response:

You can use this awk:

raw="DNS=0.0.0.0
DNS=
"

awk -F= 'NF == 2 {print $2}' <<< "$raw"
0.0.0.0

Following cut should also work:

cut -d= -f2 <<< "${raw%$'\n'}"
0.0.0.0


To store output including trailing line breaks use read with process substitution:

IFS= read -rd '' kvs < <(awk -F= 'NF == 2 {print $2}' <<< "$raw")

declare -p kvs
declare -- s="0.0.0.0

"

Code Demo:

  • Related