特殊的管道 grep/head 行为

特殊的管道 grep/head 行为

我正在帮助网络管理员使用 perl 正则表达式自动操作 SAN 中的一些快照,我们的脚本执行如下操作:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$1/')

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1 | perl -pe 's/^tcp: \[\d*\] \d*\.\d*\.\d*\.\d*:\d*,\d* (iqn\..*\..*\..*:.*-.*-.*-.*-(.*-.*-\d{4}-\d{2}-\d{2}-\d{2}:\d{2}:\d{2}\.\d*\.\d*))$/$2/')

快照的签名中有两个部分,一个嵌套在另一个中,我们使用捕获组来捕获名称和需要执行的不同后续命令的名称的一部分。我知道它一遍又一遍地运行相同的命令,并且可以稍后清理正则表达式,但基本上他们使用 perl 来输出一个括号和另一个。

tcp: [32] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1
tcp: [33] 40.40.40.101:3260,1 iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

想要捕获 icsiadm 和 grep 的结果以获得以下结果:

iqn.2001-05.com.equallogic:4-52aed6-91c5ffa78-2f0d8ae18504fee1-r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

r12prd-rbmsdata1-2012-06-29-16:07:40.108.1

我们遇到的问题是,有时通往第一行的管道会失败:

head: cannot open '–n1' for reading: No such file or directory

当然,这似乎表明头的标准输入为空,因此它正在寻找文件名。

但它没有理由永远是空的。

如果我们这样做:

varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

第二个将失败,第二个变量将为空。

然而,如果我们反转它们,那么 varsnap1 将失败:

varsnap1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)
varinit1=$(iscsiadm -m session | grep rbmsdata1 | head -n1)

这很奇怪,我们不知道发生了什么。当我们从命令行运行 iscsiadm 命令时以及 grep 之后,每次运行它都会返回相同的内容。

是不是有什么东西把管道弄乱了?

RedHat Enterprise Linux 上的 head 版本 5.97

答案1

虽然您的问题可能包含错误(长 utf8 破折号而不是正常的破折号):

$ head –n1
head: cannot open ‘–n1’ for reading: No such file or directory
$ head -n1 # ctrl-d
$ 

我认为这只是浏览器的问题,因为只有一次是这样的。head无论如何,在需要时等待输入。尝试head -n1用以下之一替换:

sed -n 1p
awk 'NR==1 {print}' # yay, no potential dash problems

好的,还有很多方法可以做到这一点,但您也可以跳过该管道元素,只grep通过添加参数来告诉仅返回第一个匹配项-m 1。或者消除两个元素并告诉perl仅在第一个匹配行上进行操作。

相关内容