AWK程序使用正则表达式来计算匹配行

时间:2016-03-03 00:02:06

标签: regex bash awk

该程序应该计算括号中以十进制数开头的行数,包含大写和小写字母的混合,并以句点结束。

我有

BEGIN {x=0}
/^\([0-9[0-9]*) [A-Z][A-z]* [a-z][a-z]* \.$/ {x = x+1}
END{print x}

我将它们拆分为多个不同的行,因为我一直在运行display(!d)语句,以便进行调试以解决问题。 要运行我使用awk -f programName.awk filename.txt 任何帮助表示赞赏。

更新

新代码读取

BEGIN{x=0}
/^\([0-9]+\)[A-Za-z]+\.$/{x++}
END{print x}

我使用vim EC.awk来编辑它。 awk -f EC.awk EC.txt运行 回来1。 EC.txt包含应计算的12行中的5行。

输入文件 vim EC.txt

(1) Line one, this should count.
(2)Line two. Should also count.
3 should not count..
4 not
(5)Yes.
(6). nope
7 OHHH mann
8 This suck
(9)Oh ya? YOU SUCK.
10 Cheaa
(11) BOI.
(12) WoW MoM. Print mofo.

更新代码

BEGIN{x=0}
/^\([0-9]+\).*?[A-Za-z]+\.$/{x++}
END{print x}

这给了我6.我相信它的计数线11(11)BOI。努力打印线以确保。

4 个答案:

答案 0 :(得分:5)

对于另一种解决方案,它更简单明了地表达意图并且也是区域设置感知的(并不总是只匹配ASCII字母),请参阅Ed Morton's helpful answer。 功能

尝试以下(POSIX兼容):

awk '/^\([0-9]+\).*([A-Z].*[a-z]|[a-z].*[A-Z]).*\.$/ { ++x } END { print x+0 }' file
  • ^\([0-9]+\)匹配一行开头括号中的十进制数字。

  • \.$匹配一行 end 的文字句点。

  • .*([A-Z].*[a-z]|[a-z].*[A-Z]).*匹配其间的任何字符串:

    • :包含至少1个大写字母,后跟至少1个小写字母。
    • :包含至少1个小写字母,后跟至少1个大写字母。
    • 因此,只要存在至少1个大写和1个小写字母,此表达式应匹配包含任何低级和大写[ASCII-only]字母混合的任何字符串。

至于为什么你的方法不起作用

  • 您的初始解决方案尝试[A-Z][A-z] *[a-z][a-z]*仅匹配行上第一个[ASCII]字母为大写的行;换句话说:行上第一个字母小写的行不匹配。
  • 您之后的解决方案尝试[A-Za-z]+,由于使用了匹配其字符的单个字符集任何 仅匹配包含的行大写小写字母,这就是行(11) BOI.也匹配的原因。

答案 1 :(得分:3)

如果这是预期的输出,则为idk,因为您没有在问题中包含该输出,但我只是在您的问题count the number of lines begin with a decimal number in parenthesis, containing a mix of both upper and lower case letters and end with a period中编写了您所说的内容并添加了print以便您可以看看它匹配的内容,看看它是否符合您的要求:

$ cat tst.awk
/^\([0-9]+\)/ && /[[:upper:]]/ && /[[:lower:]]/ && /\.$/ { print; cnt++ }
END { print cnt+0 }

$ awk -f tst.awk file
(1) Line one, this should count.
(2)Line two. Should also count.
(5)Yes.
(9)Oh ya? YOU SUCK.
(12) WoW MoM. Print mofo.
5
不要认为awk语句的条件部分必须是正则表达式,就像它是sed或grep一样,因为它不是 - 它可能是ands /的复合条件正则表达式是什么让你的代码更简单,更清晰,就像在这种情况下恕我直言。

答案 2 :(得分:1)

您的正则表达式尝试匹配以下文本when

我认为在发布问题时你错过了(1 or more digits)<space><1 or more Uppercase><space><1 or more lowercase><space><period>以防数字,如果你想要小写后跟大写,那么你必须使用你的正则表达式;但是既然你在问题中提到它可以是大写和小写的混合,你将不得不使用][A-Za-z]+确保1个或更多,+等同于[a-z]+

[a-z][a-z]*

如果你想要一个或多个小写字母后跟一个或多个大写字母,那么你将不得不使用这个正则表达式:

$cat file.txt 
(1) aBCdadg .
(2) dgshdf .
(3) DFHFH .
xyz
abcd
(56) sdflgkfd .
$ cat prgm.awk 
BEGIN {x=0}

/^\([0-9]+\) [A-Za-z]+ \.$/ {x++}

END {print x}
$ awk -f prgm.awk file.txt 
4
$

编辑:

/^\([0-9]+\) [a-z]+ [A-Z]+ \.$/ {x++}

编辑2:对不起,我急着去某个地方并且离开了我的电脑几个小时。由于它更清楚你需要什么,我只是更新答案的完整性。

$ cat file.txt 
(1) Line one, this should count.
(2) Line two. Should also count.
3 should not count..
4 not
(5)Yes.
(6). nope
7 OHHH mann
8 This suck
(9) Oh ya? YOU SUCK.
10 Cheaa
(11) BOI.
(12) WoW MoM. Print mofo.
$ cat prgm.awk 
BEGIN {x=0}

/^\([0-9]+\)\s*[A-Za-z0-9., ]+\s*\./{x++}

END {print x}
$ awk -f prgm.awk file.txt 
5
$

通过接受除我的任何人的答案来标记问题:P:)

编辑3:给别人信用。

答案 3 :(得分:1)

最好将条件细分为单独的正则表达式:

  1. 行以括号中的十进制数开头:/^\([0-9]+\)//^\([[:digit:]]+\)/
  2. 包含大写字母:/[A-Z]//[[:upper:]]/
  3. 包含小写字母:/[a-z]//[[:lower:]]/
  4. 以句点结束:/\.[ \t]*$/[ \t]*捕获尾随空格(如果有的话)......)
  5. 现在只需结合这些条件:

    awk '/^\([[:digit:]]+\)/ && /\.[ \t]*$/ && /[[:lower:]]/ && /[[:upper:]]/ { print }' file
    (1) Line one, this should count.
    (2)Line two. Should also count.
    (5)Yes.
    (9)Oh ya? YOU SUCK.
    (12) WoW MoM. Print mofo.
    

    然后浏览wc -l以获取行数:

    awk '//^\([[:digit:]]+\)/ && /\.[ \t]*$/ && /[[:lower:]]/ && /[[:upper:]]/ { print }' file | wc -l
    5
    

    或者,保持自己的数量:

    awk '/^\([[:digit:]]+\)/ && /\.[ \t]*$/ && /[[:lower:]]/ && /[[:upper:]]/ { i++ } END{print i}' file
    5
    

    你的正则表达式的问题:

    /^\([0-9]+\).*?[A-Za-z]+\.$/
                ^^                       Any string of characters
                     ^ ^                 Could be 'UPPER' or 'lower' 
    
    1. .*匹配前往的所有字符(包括空格),
    2. [A-Za-z]+匹配一系列大写和/或小写字母,但不会告诉您是否同时使用这两个字母。
    3. 差不多,但是你没有正确检测到那些没有包含该正则表达式的大写和小写字母的行。

相关问题