我想用来awk
将输入文件的内容排序到不同的输出文件中。
简单的例子
假设有以下输入文件:
$cat sample.txt
START Unix Linux START Solaris Aix SCO
该awk
程序
awk '/START/{x="F"++i;}{print > x}' sample.txt
将以下输出生成到文件中:
$ cat F1
START Unix Linux
$ cat F2
START Solaris Aix SCO
实际使用场景
当我将这种技术应用到我的实际用例中时,
awk '/Certificate Revocation List (CRL):/{x="F"++i;}{print > x}' test_cert.pem
不提取从以下位置开始的内容Certificate Revocation List (CRL):
相反,它给出以下错误:
awk: cmd. line:1: (FILENAME=test_cert.pem FNR=1) fatal: expression for `>' redirection has null string value
我尝试将模式放在引号中,但它不起作用,不确定模式是否是多字的,我们如何提取内容。
外观test_cert.pem
如下:
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = XX, O = XXXXX, OU = 0003 374154744412350, CN = XXX
Last Update: Aug 15 04:37:16 2021 GMT
Next Update: Sep 23 03:47:16 2021 GMT
CRL extensions:
X509v3 CRL Number:
209
X509v3 Authority Key Identifier:
keyid:09:DF:3B:15:GE:10:08:D5:86:8F:5B:E7:E6:36:B9:A1:A8:1A:83:18
Revoked Certificates:
Serial Number: AAS60F19DABCDA8AGHIK3E4A59988AAFDA8E6
Revocation Date: Jan 29 12:45:09 2021 GMT
Serial Number: GGF0HHHABCDA8AGHIK3E4A599KKKAFDA8E6
Revocation Date: Jul 25 4:32:24 2021 GMT
Signature Algorithm: sha256WithRSAEncryption
1e:cc:8e:9d:gv:ae:eb:0a:67:95:4b:8b:b6:5d:9e:bd:48:42:
a5:25:e8:eb:b2:22:BV:42
-----BEGIN X509 CRL-----
MIIDLLKKARMCAQEwLLKKAOKONcNAQELBQYYUzvgfzELLLKKA1UEBhMCRlIxDzANBgNV
mZ7YI0YYUzvgrzYYUzvgz9Deb78UGbaedXkYYUzvgr5Hu1Zm16YYUzvgXo67IiNUI=
-----END X509 CRL-----
答案1
您的情况有两个问题。
第一个问题是您的匹配模式包含正则表达式特有的字符,在本例中为( ... )
.您需要转义它们才能让您的程序真正找到匹配项。目前,您的程序找不到匹配项,因此x
从未初始化。这就是“重定向具有空字符串值”错误的原因。
此外,即使正则表达式的表述正确,对于任何出现的情况都会失败前字符串的第一次出现Certificate Revocation List (CRL):
。所以你需要
- 更正你的正则表达式
- 确保除非
x
初始化,否则不会打印任何内容。
你可以将你的程序更改为
awk '/Certificate Revocation List \(CRL\):/{x="F"++i;}{if (x) print > x}' test_cert.pem
它会再次起作用。
但这又是一个例子为什么如果您只是查找固定字符串,则不应使用正则表达式匹配。要强化您的程序以解决此类问题,请使用
awk '$0=="Certificate Revocation List (CRL):"{x="F"++i}{if (x) print >x}' test_cert.pem
反而。
答案2
输入文件顶部有一个空行。当awk
代码读取此内容时,该x
变量没有值,因此print >x
执行时会触发错误。
这是由于awk
代码期待要在第一行匹配的正则表达式,以便x
将其设置为某个值。
您可以通过在块F0
中启动 x 来解决此问题BEGIN
:
awk 'BEGIN { x = "F0" } /...your RE.../ { x = "F" ++i } { print >x }' file
这将产生将正则表达式第一个匹配之前的所有行输出到文件的效果F0
。
您可能还想丢弃x
设置之前读取的任何内容:
awk '/...your RE.../ { x = "F" ++i } x != "" { print >x }' file
此外,正则表达式需要对其括号进行转义,因为它们很特殊:
awk '/Certificate Revocation List \(CRL\):/ { x = "F" ++i } x != "" { print > x }'