Linux 中基于 Awk 的文件数据过滤
Awk based filtering of data on a file in Linux
我有一个试图通过 awk 过滤的文件数据,我能够过滤数据但希望 awk 语句更简单地写成一行:
文件内容:
Entity Name
Value
Unknown dbs636294051.klm.bet.com: /opt
N/A
Unknown dbs636294051.klm.bet.com: /tmp
N/A
Unknown dbs636294051.klm.bet.com: /var
N/A
我的试用期:
awk '!/^N/{ if( ~ /klm/) print }' file | awk -F":" '{print }'
以上有效,但我正在寻找是否可以将其修剪到之前的管道:
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
sub
函数可用于 trim 冒号及其后的任何内容 </code>:</p>
<pre><code>awk '!/^N/ && ~ /klm/ {sub(/:.*$/,"",); print }' file
您可以编写单个 awk 命令,将字段分隔符设置为 1 个或多个空格或 :
,检查字段 1 是否不以 N
广告开头并且它确实包含 klm
具体来说,你也可以写成^N\/A$
感谢@Renaud Pacalet and @Wiktor Stribiżew 的评论,命令可以如下所示:
awk -F'[[:blank:]]+|:' '!/^N/ && ~ /klm/{print }' file
部分
awk -F'[[:blank:]]+|:' ' # Set the field separator to either 1+ spaces or tabs or a semicolon
!/^N/ && ~ /klm/ # If the record does not start with `N` and field 2 does contain klm
{print } # Print the second column
输出
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
这是一个快速而肮脏的方法,适用于给定的示例。
如果你有更多的过滤规则,也很容易调整。
awk -F'[:\s]' 'NR>1 && ~/klm/{print }' f
636294051.klm.bet.com
636294051.klm.bet.com
636294051.klm.bet.com
更新,另一种方法:
awk '~/klm/ && (([=11=]=)+sub(/:.*/,""))' f
awk '/Unknown/{gsub(/:/,"",$0);打印 $2}' 文件
当您有两个带有不同字段分隔符的管道 awk
命令时,例如
awk '!/^N/{ if( ~ /klm/) print }' file | awk -F":" '{print }'
您可以使用 split
函数将其转换为单个 awk
命令,在本例中为
awk '!/^N/{ if( ~ /klm/){split(,arr,":");print arr[1]}}' file
免责声明:此答案仅适用于将 2 awk
s 更改为单个,其他改进方法不在本答案的范围内。
我有一个试图通过 awk 过滤的文件数据,我能够过滤数据但希望 awk 语句更简单地写成一行:
文件内容:
Entity Name
Value
Unknown dbs636294051.klm.bet.com: /opt
N/A
Unknown dbs636294051.klm.bet.com: /tmp
N/A
Unknown dbs636294051.klm.bet.com: /var
N/A
我的试用期:
awk '!/^N/{ if( ~ /klm/) print }' file | awk -F":" '{print }'
以上有效,但我正在寻找是否可以将其修剪到之前的管道:
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
sub
函数可用于 trim 冒号及其后的任何内容 </code>:</p>
<pre><code>awk '!/^N/ && ~ /klm/ {sub(/:.*$/,"",); print }' file
您可以编写单个 awk 命令,将字段分隔符设置为 1 个或多个空格或 :
,检查字段 1 是否不以 N
广告开头并且它确实包含 klm
具体来说,你也可以写成^N\/A$
感谢@Renaud Pacalet and @Wiktor Stribiżew 的评论,命令可以如下所示:
awk -F'[[:blank:]]+|:' '!/^N/ && ~ /klm/{print }' file
部分
awk -F'[[:blank:]]+|:' ' # Set the field separator to either 1+ spaces or tabs or a semicolon
!/^N/ && ~ /klm/ # If the record does not start with `N` and field 2 does contain klm
{print } # Print the second column
输出
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
这是一个快速而肮脏的方法,适用于给定的示例。 如果你有更多的过滤规则,也很容易调整。
awk -F'[:\s]' 'NR>1 && ~/klm/{print }' f
636294051.klm.bet.com
636294051.klm.bet.com
636294051.klm.bet.com
更新,另一种方法:
awk '~/klm/ && (([=11=]=)+sub(/:.*/,""))' f
awk '/Unknown/{gsub(/:/,"",$0);打印 $2}' 文件
当您有两个带有不同字段分隔符的管道 awk
命令时,例如
awk '!/^N/{ if( ~ /klm/) print }' file | awk -F":" '{print }'
您可以使用 split
函数将其转换为单个 awk
命令,在本例中为
awk '!/^N/{ if( ~ /klm/){split(,arr,":");print arr[1]}}' file
免责声明:此答案仅适用于将 2 awk
s 更改为单个,其他改进方法不在本答案的范围内。