使用 sed 查找并仅保留其中包含 2 个字母字符的行

使用 sed 查找并仅保留其中包含 2 个字母字符的行

我有一个包含许多这样的行的文件

33B87401
33B87402
33B87403
33B8EE44
33B87405
33B87406
33B87407
33B87408
33B87409
33B8740A
33B8740B
33B8740C
33B87D0D
33B8740E
33B8740F
33B87410
33B87411
33B87C1E
33B87CC3
33B87C1C

我正在寻找一种方法来仅保留只有 2 个字母字符的行

这个例子的输出是

33B8740A
33B8740B
33B8740C
33B8740E
33B8740F

这是另一个列表

8765C3E3
8765C3E4
8765C3E5
8765C3E6
8765C3E7
8765C3E8
8765C3E9
8765C3EA
8765C3EB
8765C3EC
8765C3ED
8765C3EE
8765C3EF
8765C3F0

阅读许多 sed 和 awk 的示例,并且非可以重现这一点。

谢谢

答案1

sed -ne's/[[:alpha:]]//3;t' -e's//&/2p'  <in >out

...将s///替换掉[[:alpha:]]类中任何字符在一行中第三次出现的位置。随后t判断此替换是否成功,如果成功,则从脚本中分支出来。

因为sed被指示-n自动打印,所以具有三个或更多字母字符的输入行此时被有效地从输出中删除,并且第二个s///替换语句剩下的唯一输入行是具有两个或更少字母字符的输入行。

第二个替换使用//左侧的空正则表达式 - 对于sed,(更有效率)指的是最近编译的/regexp/- 所以可以s/[[:alpha:]]/...再次读作。这个尝试将s///一行中第二次出现的字母字符替换为&自身 - 因此会导致有效的空操作并且不会对该行进行实际修改。然而,如果它可以成功地做到这一点,那么该行也会被p打印到输出。

总之 - 第一个s///替换有效地从输出中删除与三个或更多字母字符匹配的所有输入行,第二个替换p会保留剩余内容以仅输出与两个字母字符匹配的输入行。

...w/ grep...

grep -xE '([0-9]*[[:alpha:]]){2}' <in >out

该声明并不完全按照要求执行。它从输入中仅选择那些仅由字母数字组成的行,并且在该子集中仅选择那些匹配不超过或少于两个字母的行,其中第二个必须是最后一个字符。该语句将从示例输入生成示例所需的输出。

不过,要按照要求去做:

grep -xE '([^[:alpha:]]*[[:alpha:]]){2}[^[:alpha:]]*'

该语句将选择与不超过或少于两个字母字符匹配的输入行,这些字母字符可以在输入行的任何位置找到,并且可以由任意数量的^非字母字符分隔。

grep-x开关在两种情况下都使用。不过,如果^行头锚点和$行尾锚点分别(前置|附加)附加到正则表达式,则任何一个语句都可以不使用。该-x开关表示一个全线匹配 - 因此正则表达式必须从头到尾完整地描述所有匹配的输入行。

答案2

我会用perl

perl -ne 'print if length s/\d//gr == 2'

其中使用:

  • -n隐式包装while ( <> ) {循环
  • s///r返回替换后的文本,但不修改原始文本。
  • 所以我们删除所有数字,然后查看字符串长度
  • 如果是 2,则打印该行。

注意:这将从行中删除数字,留下非数字。你可以用[^A-Z]它来代替。

或者 - 如果更清楚的话:

perl -ne 'print if (()=m/([A-Z])/g) == 2'

这适用于perl不支持该r标志的旧版本。它使用正则表达式匹配来选择文本,并计算数组元素(匹配)的数量。如果是 2,则打印该行。

答案3

我刚刚写了一个简单的 python 脚本,它完全符合你的要求,我在你的输入上测试了它,它工作得很好。

   #!/usr/bin/python

   def count_letters(input):
     count=0
     for char in input:
       if char.isalpha():
         count += 1
     return count

  fh=open('test_input','r')
  for line in fh.readlines():
    if count_letters(line) == 2 :
      print line

答案4

awk

awk '{x=$0; gsub(/[^[:alpha:]]/, "", x)};length(x) == 2' file

这会将每一行设置为一个变量,然后用空字符串x替换其中的所有非字母字符。x如果如此修改的长度x等于2,则相关行符合条件

或者,与grep

grep '^[^[:alpha:]]*[:[:alpha:]][^[:alpha:]]*[:[:alpha:]][^[:alpha:]]*$' file

相关内容