剪切粘贴,同时为空匹配保留最后一个空白行(awk 或 sed)
Cut-n-paste while preserving last blank line for empty match (awk or sed)
我有一个两行的“keyword=keyvalue”行模式(有选择地从systemd/networkd.conf
文件中删除):
DNS=0.0.0.0
DNS=
并需要以下两行答案:
0.0.0.0
但是如果最后一行模式匹配导致空匹配,所有使用 sed
或 awk
的尝试都会导致省略换行符。
编辑:
哦,最后一件事,这个多行跟随切割结果必须存储回一个 bash 变量中,该变量也包含这个相同的“最后一个空白行”,所以这是保留最后一个的两步操作 -空行
- 等号
=
符号之前(或之后保存内容)的多行前置剪切,同时保留换行符...以防出现空结果(这是这里的关键)。或者可能是 jerry-rig 一个弱修复来附加一个新行,以防最后一行的匹配结果为空。
- 将多行结果保存回 bash 变量
sed
方法
当在 bash shell 中执行剪切并包含匹配字符时,sed
将删除具有空模式匹配的任何空行:
raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"
kvs="$(echo "$rawp"| sed -e '/^[^=]*=/s///')"
echo "result: '${kvs}'"
给出结果:
0.0.0.0
没有对应的空行
awk
方法
awk有同样的问题:
raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"
kvs="$(echo "$rawp"| awk -F '=' -v OFS="" '{=""; print}')"
echo "result: '${kvs}'"
给出相同的答案(它删除了空行)。
请指教
不知何故,我需要以下答案:
0.0.0.0
以包含 0.0.0.0
和一个空行的两行输出形式。
其他观察结果
我还注意到,如果我提供如下的 3 行数据(两行有键值,中间一行没有键值:
DNS=0.0.0.0
DNS=
DNS=999.999.999.999
sed
和awk
都提供了正确答案:
0.0.0.0
999.999.999.999
奇怪,嗯?
以上正则表达式(sed
和 awk
)适用于:
- 一行及其键值,
- 任何行,只要任何行都有其非空键值,但是
- 最后一行必须有一个键值。
当最后一行有一个空键值时就不起作用。
:-/
你可以使用这个 awk
:
raw="DNS=0.0.0.0
DNS=
"
awk -F= 'NF == 2 {print }' <<< "$raw"
0.0.0.0
以下 cut
也应该有效:
cut -d= -f2 <<< "${raw%$'\n'}"
0.0.0.0
要存储包括尾随换行符的输出,请使用 read
和进程替换:
IFS= read -rd '' kvs < <(awk -F= 'NF == 2 {print }' <<< "$raw")
declare -p kvs
declare -- s="0.0.0.0
"
我有一个两行的“keyword=keyvalue”行模式(有选择地从systemd/networkd.conf
文件中删除):
DNS=0.0.0.0
DNS=
并需要以下两行答案:
0.0.0.0
但是如果最后一行模式匹配导致空匹配,所有使用 sed
或 awk
的尝试都会导致省略换行符。
编辑: 哦,最后一件事,这个多行跟随切割结果必须存储回一个 bash 变量中,该变量也包含这个相同的“最后一个空白行”,所以这是保留最后一个的两步操作 -空行
- 等号
=
符号之前(或之后保存内容)的多行前置剪切,同时保留换行符...以防出现空结果(这是这里的关键)。或者可能是 jerry-rig 一个弱修复来附加一个新行,以防最后一行的匹配结果为空。 - 将多行结果保存回 bash 变量
sed
方法
当在 bash shell 中执行剪切并包含匹配字符时,sed
将删除具有空模式匹配的任何空行:
raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"
kvs="$(echo "$rawp"| sed -e '/^[^=]*=/s///')"
echo "result: '${kvs}'"
给出结果:
0.0.0.0
没有对应的空行
awk
方法
awk有同样的问题:
raw="DNS=0.0.0.0
DNS=
"
rawp="$(printf "%s\n" "$raw")"
kvs="$(echo "$rawp"| awk -F '=' -v OFS="" '{=""; print}')"
echo "result: '${kvs}'"
给出相同的答案(它删除了空行)。
请指教
不知何故,我需要以下答案:
0.0.0.0
以包含 0.0.0.0
和一个空行的两行输出形式。
其他观察结果
我还注意到,如果我提供如下的 3 行数据(两行有键值,中间一行没有键值:
DNS=0.0.0.0
DNS=
DNS=999.999.999.999
sed
和awk
都提供了正确答案:
0.0.0.0
999.999.999.999
奇怪,嗯?
以上正则表达式(sed
和 awk
)适用于:
- 一行及其键值,
- 任何行,只要任何行都有其非空键值,但是
- 最后一行必须有一个键值。
当最后一行有一个空键值时就不起作用。
:-/
你可以使用这个 awk
:
raw="DNS=0.0.0.0
DNS=
"
awk -F= 'NF == 2 {print }' <<< "$raw"
0.0.0.0
以下 cut
也应该有效:
cut -d= -f2 <<< "${raw%$'\n'}"
0.0.0.0
要存储包括尾随换行符的输出,请使用 read
和进程替换:
IFS= read -rd '' kvs < <(awk -F= 'NF == 2 {print }' <<< "$raw")
declare -p kvs
declare -- s="0.0.0.0
"