在Awk中使用RegExp

时间:2017-11-13 18:57:00

标签: regex bash csv awk

我有CSV文件:

SELECT Department_no, COUNT(Staff_id) TheCount
FROM ManagerOrBoss
GROUP BY Department_no
HAVING TheCount = (
    SELECT MAX(Num) 
    FROM (
        SELECT Department_no, COUNT(Staff_id) Num 
        FROM ManagerOrBoss 
        GROUP BY Department_no
    ) as A
)

并希望使用RegExp和Awk(或Gawk)制作此CSV文件:

<iframe src="https://localhost/get/44bc40f3bc04f65b7a35"></iframe>|name_1
<iframe src="https://localhost/get/5db0d477d707121934ff"></iframe>|name_2
<iframe src="https://localhost/get/6c95bd2b32ed45989c61"></iframe>|name_3
<iframe src="https://localhost/get/0a9c4655800e8a7b9ea2"></iframe>|name_4
<iframe src="https://localhost/get/754953b57a32e2841bda"></iframe>|name_5

我在Grep工作了RegExp

44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5

但是这个RegExp在Awk中不起作用。我认为我在Awk中使用regexp是不正确的,或者这种类型的RegExp在Awk中不起作用。

$ grep -Po "[A-Za-z]*+\d++\w++" example.txt 
44bc40f3bc04f65b7a35
5db0d477d707121934ff
6c95bd2b32ed45989c61
0a9c4655800e8a7b9ea2
754953b57a32e2841bda

Just Awk正常工作:

$ awk -F "|" 'match($1, /[A-Za-z]*+\d++\w++/, a) {print a[0]"|"$2}' example.txt 
db0d477d707121934ff|name_2
bd2b32ed45989c61|name_3
bda|name_5

4 个答案:

答案 0 :(得分:3)

尝试:

$ awk -F'<iframe src="https://localhost/get/|"></iframe>' '{print $2 $3}' file
44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5

这可以通过将输入字段分隔符设置为 iframe src="https://localhost/get/"></iframe>来实现,在这种情况下,您想要的输出是第二个字段,后跟第三个字段。< / p>

使用匹配的替代方法

$ awk -F "|" 'match($1, /[[:xdigit:]]{20}/, a) {print a[0]"|"$2}' file
44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5

请注意,awk支持POSIX正则表达式。这意味着它可以识别[[:digit:]][[:alnum:]]等字符类,但不一定是\d\w。作为特定于GNU的扩展,gawk支持\w(但不支持\d)。为了便于携带,请坚持使用man 7 regex中显示的POSIX类。

又一种方法

你的正则表达式[A-Za-z]*+\d++\w++可以翻译成awk,如下所示:

$ awk -F "|" 'match($1, /[[:alpha:]]*[[:digit:]]+[[:alnum:]]+/, a) {print a[0]"|"$2}' file
44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5

请注意,此方法要求20个字符的十六进制字符串至少包含一个数字。

答案 1 :(得分:0)

  1. 示例中awk和grep调用之间的区别在于grep中的-P选项,它代表&#34;使用Perl regexp&#34;。如果用-E替换它,它就像你的awk运行一样。 Awk不支持Perl扩展。

  2. 你的正则表达式最好修复,我认为你不需要这些额外的+标志。如果我可以假设你需要所有字母或数字后得到/那么我宁愿写:

    awk -F&#34; |&#34; &#39;匹配($ 1,/ get /([A-Za-z0-9] +)/,a){print a [1]&#34; |&#34; $ 2}&#39; example.txt

  3. 这里我们使用[A-Za-z0-9] +匹配/ get之后的任意数量的小或大写字母或数字,使用[1]在括号内打印匹配的组而不是整个匹配模式a [0],包括get /

答案 2 :(得分:0)

awk '{gsub(/<.*get\//,"")gsub(/".*e>/,"")}1'  file

44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5

答案 3 :(得分:0)

这是另一种解决方案:

awk -F"[/\">|]" 'BEGIN{ OFS = "|" }{ print $6, $11 }' yourfile

在开头使用-F选项时,字段分隔符可以是/,&#34;,&gt;和|。完成后,您只需打印包含所需输出的$ 6和$ 11字段以及输出字段分隔符。

输出:

44bc40f3bc04f65b7a35|name_1
5db0d477d707121934ff|name_2
6c95bd2b32ed45989c61|name_3
0a9c4655800e8a7b9ea2|name_4
754953b57a32e2841bda|name_5