如何使用 awk 进行数字比较并创建列表 - 在 macOS 上使用带有 CRLF 行结尾的 Awk
how to use awk to do a number comparisons and create a list - using Awk on macOS with CRLF line endings
我试图列出比我列出的值更大的值(来自我的 knife
命令的输出)。我正在尝试使用 awk
来做到这一点,我一直在研究示例并想出了这个。但是,我的预期输出不起作用。
例如,使用此命令,我得到以下输出:
knife ssh -x foobar -a ec2.local_ipv4 "chef_environment:prod AND roles:db_cluster AND AND ipaddress:10.1.*" 'netstat -na | grep EST | wc -l'
输出:
10.1.3.129 2273
10.1.3.130 2533
10.1.3.131 1981
10.1.2.133 1965
现在,我想使用 awk
,因为我只想过滤那些值(第 2 列,删除 IP)> 2000。
我尝试了以下 awk
语句,但无济于事
knife ssh -x foobar -a ec2.local_ipv4 "chef_environment:prod AND roles:db_cluster AND AND ipaddress:10.1.*" 'netstat -na | grep EST | wc -l' \
| awk '{if ( > 2000) print ; else echo "Nothing to print"}`
输出:
10.1.3.129 2273
10.1.3.130 2533
10.1.3.131 1981
10.1.2.133 1965
预期输出:
2273
2533
tl;dr
最简单的方法是在将输出传递给 awk
之前从输出中删除 \r
个实例:
knife ... | tr -d '\r' | awk ...
这假设 \r
个实例仅作为 \r\n
对的一部分出现以指定行结尾,通常情况就是如此。
根据您的评论,我们现在知道您的输入具有 Windows 样式的 CRLF (\r\n
) 行结尾 并且您在 macOS Sierra (10.12).
也就是说,您的样本输出与您问题中的 awk
命令不一致。
撇开这个问题不谈,有两种基本方法:
(a) 将 \r\n
(CRLF) 序列翻译成 \n
(LF) first。
(b) 通过修改 Awk 的输入记录分隔符解决此问题。
以下示例使用简化的输入和简化的命令来关注核心问题:
printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n'
用于生成 2 个以 CRLF 终止(\r\n
终止)的输入行,每个行包含 2 个以空格分隔的字段。
awk '{ print }' | cat -e
- 或其变体 - 使用 awk
从每行打印第二个空格分隔的字段,并且 cat -e
用于可视化控制字符在输出中:$
表示 \n
(LF) 字符。 (Unix 术语中的行尾),其他控制字符可视化为 ^<letter>
,即 caret notation;因此,\r
(CR) 表示为 ^M
.
默认情况下,\r
将 包含在输出中 ,因为 awk
不认为它是空白(这些行被分割成字段) - 这显然是不希望的。输出如下所示,其中 ^M
表示不希望包含的 \r
:
2273^M$
2533^M$
使用有效的解决方案,\r
将 不包含在输出中, 输出如下所示(注意没有^M
):
2273$
2533$
基于方法 (a) 的解决方案:
通常,实用程序 dos2unix
用于将 Windows 风格的换行符转换为 Unix 风格的换行符,但该实用程序不会出现使用 macOS。
但是,通过 Homebrew 很容易安装它。
然后使用 knife ... | dos2unix | awk ...
.
(或者先将输出发送到文件并在进一步处理之前就地更新该文件:dos2unix file
。)
或者无耻自夸部给你带来的,你可以安装我的nws
CLI;如果你安装了Node.js,安装它通过简单地 运行 [sudo] npm install -g nws-cli
然后使用 knife ... | nws --lf | awk ...
.
(或者,先将输出发送到文件并在进一步处理之前就地更新该文件:
nws --lf -i file
; nws
还可以将 LF 转换为 CRLF,并提供其他与空格相关的功能。)
还有一些相当简单的方法可以使用常用的 macOS 实用程序 - 请参阅我的 this answer。
最简单的库存实用程序解决方案是使用 tr
盲目删除任何 \r
个实例:
$ printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n' |
tr -d '\r' | awk '{ print }' | cat -e
2273$
2533$
基于方法 (b) 的解决方案:
$ printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n' |
awk -v RS='\r' 'NF {print }' | cat -e
2273$
2533$
请注意 -v RS='\r'
如何将 \r
定义为 RS
,输入记录分隔符,这意味着它会自动从 awk
的每个记录(行)中排除读取并拆分为字段。
NF
,作为 条件 放置在操作 ({...}
) 之前是必要的,以消除读取最终 [= 产生的空行22=]作为单独的记录。
- 如果我们可以将
RS
定义为\r\n
,这可以避免,但是,遗憾的是,macOS 上的 BSD Awk 不支持多-字符输入记录分隔符(符合POSIX spec.).
然而,通过 Homebrew,你可以安装 GNU Awk,它支持这样的分隔符,这将简化命令为:
gawk -v RS='\r\n' '{print }'
我试图列出比我列出的值更大的值(来自我的 knife
命令的输出)。我正在尝试使用 awk
来做到这一点,我一直在研究示例并想出了这个。但是,我的预期输出不起作用。
例如,使用此命令,我得到以下输出:
knife ssh -x foobar -a ec2.local_ipv4 "chef_environment:prod AND roles:db_cluster AND AND ipaddress:10.1.*" 'netstat -na | grep EST | wc -l'
输出:
10.1.3.129 2273
10.1.3.130 2533
10.1.3.131 1981
10.1.2.133 1965
现在,我想使用 awk
,因为我只想过滤那些值(第 2 列,删除 IP)> 2000。
我尝试了以下 awk
语句,但无济于事
knife ssh -x foobar -a ec2.local_ipv4 "chef_environment:prod AND roles:db_cluster AND AND ipaddress:10.1.*" 'netstat -na | grep EST | wc -l' \
| awk '{if ( > 2000) print ; else echo "Nothing to print"}`
输出:
10.1.3.129 2273
10.1.3.130 2533
10.1.3.131 1981
10.1.2.133 1965
预期输出:
2273
2533
tl;dr
最简单的方法是在将输出传递给 awk
之前从输出中删除 \r
个实例:
knife ... | tr -d '\r' | awk ...
这假设 \r
个实例仅作为 \r\n
对的一部分出现以指定行结尾,通常情况就是如此。
根据您的评论,我们现在知道您的输入具有 Windows 样式的 CRLF (\r\n
) 行结尾 并且您在 macOS Sierra (10.12).
也就是说,您的样本输出与您问题中的 awk
命令不一致。
撇开这个问题不谈,有两种基本方法:
(a) 将
\r\n
(CRLF) 序列翻译成\n
(LF) first。(b) 通过修改 Awk 的输入记录分隔符解决此问题。
以下示例使用简化的输入和简化的命令来关注核心问题:
printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n'
用于生成 2 个以 CRLF 终止(\r\n
终止)的输入行,每个行包含 2 个以空格分隔的字段。awk '{ print }' | cat -e
- 或其变体 - 使用awk
从每行打印第二个空格分隔的字段,并且cat -e
用于可视化控制字符在输出中:$
表示\n
(LF) 字符。 (Unix 术语中的行尾),其他控制字符可视化为^<letter>
,即 caret notation;因此,\r
(CR) 表示为^M
.默认情况下,
\r
将 包含在输出中 ,因为awk
不认为它是空白(这些行被分割成字段) - 这显然是不希望的。输出如下所示,其中^M
表示不希望包含的\r
:2273^M$ 2533^M$
使用有效的解决方案,
\r
将 不包含在输出中, 输出如下所示(注意没有^M
):2273$ 2533$
基于方法 (a) 的解决方案:
通常,实用程序 dos2unix
用于将 Windows 风格的换行符转换为 Unix 风格的换行符,但该实用程序不会出现使用 macOS。
但是,通过 Homebrew 很容易安装它。
然后使用 knife ... | dos2unix | awk ...
.
(或者先将输出发送到文件并在进一步处理之前就地更新该文件:dos2unix file
。)
或者无耻自夸部给你带来的,你可以安装我的nws
CLI;如果你安装了Node.js,安装它通过简单地 运行 [sudo] npm install -g nws-cli
然后使用 knife ... | nws --lf | awk ...
.
(或者,先将输出发送到文件并在进一步处理之前就地更新该文件:
nws --lf -i file
; nws
还可以将 LF 转换为 CRLF,并提供其他与空格相关的功能。)
还有一些相当简单的方法可以使用常用的 macOS 实用程序 - 请参阅我的 this answer。
最简单的库存实用程序解决方案是使用 tr
盲目删除任何 \r
个实例:
$ printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n' |
tr -d '\r' | awk '{ print }' | cat -e
2273$
2533$
基于方法 (b) 的解决方案:
$ printf '10.1.3.129 2273\r\n10.1.3.130 2533\r\n' |
awk -v RS='\r' 'NF {print }' | cat -e
2273$
2533$
请注意 -v RS='\r'
如何将 \r
定义为 RS
,输入记录分隔符,这意味着它会自动从 awk
的每个记录(行)中排除读取并拆分为字段。
NF
,作为 条件 放置在操作 ({...}
) 之前是必要的,以消除读取最终 [= 产生的空行22=]作为单独的记录。
- 如果我们可以将
RS
定义为\r\n
,这可以避免,但是,遗憾的是,macOS 上的 BSD Awk 不支持多-字符输入记录分隔符(符合POSIX spec.).
然而,通过 Homebrew,你可以安装 GNU Awk,它支持这样的分隔符,这将简化命令为:
gawk -v RS='\r\n' '{print }'