删除某些列长度的行?

时间:2017-05-11 12:53:26

标签: sorting awk sed string-length

我有一个文本文件,如下所示:

A : 1
Boy : 3
Ahoy! : 7
more : 8

我必须删除长度小于或等于3个字母长的行。输出应如下所示:

Ahoy! : 7
more : 8

由于

1 个答案:

答案 0 :(得分:1)

OP有点不明确(并且由于comm(ent | un)),根据我对问题的解释,我们发展了一些可能的解决方案。

我的1 st 脚本filter.awk

$3 <= 3 { next }
{ print $0 }

仅考虑3 rd 列(使用标准空白分隔)。因此,将冒号后的数字与常数3进行比较。

您的测试输入filter.txt

A : 1
Boy : 3
Ahoy! : 7
more : 8

测试:

$ awk -f filter.awk filter.txt
Ahoy! : 7
more : 8

$
埃德莫顿指出,它可以做得更短:

$3 > 3

这对我来说也是新的。 (可能是,我对lex感到困惑,其工作方式相反:在lex / flex中,所有无法比拟的东西都会被回应。)

更强大的方法是使用冒号(:)作为列分隔符(或者像在awk:field分隔符中命名的那样)。通过分配内置变量FS可以实现更改字段分隔符。这可以使用命令行参数-F或在特殊BEGIN规则中的赋值来完成,该规则始终在开始时执行。 (我更喜欢写字母的字母&#34;自包含&#34;。)

因此,filter2.awk(即filter.awk V2.0):

BEGIN { FS = ":" }
$2 <= 3 { next }
{ print $0 }

或考虑我今天学到的东西:

BEGIN { FS = ":" }
$2 > 3

测试:

$ awk -f filter2.awk filter.txt
Ahoy! : 7
more : 8

$

对OP的另一种解释可能是考虑每行第一列中连续字母的数量。为实现这一目标,一些内置函数发挥作用:

  1. gensub()一个强大的替换函数,遗憾的是只在GNU awk中可用

  2. length()返回字符串的长度(或数组中元素的数量)

  3. 为此我使用扩展测试输入filter2.txt

    A : 1
    Boy : 3
    Ahoy! : 7
    more : 8
    Hello World : 0
    Hello! World. : 0
    Hi World : 0
    

    filter3.awk(即filter.awk V3.0):

    length(gensub(/(^[A-Za-z]+).*$/, "\\1", 1, $1)) > 3
    

    测试:

    $ awk -f filter3.awk filter2.txt
    Ahoy! : 7
    more : 8
    Hello World : 0
    Hello! World. : 0
    
    $
    

    由于在这种情况下字段分隔符未更改,因此1 st 字段由直到1 st 空格的字符组成。模式(^[A-Za-z]+)捕获文本开头的所有字母,并将它们存储到1个 st 内部缓冲区中。 .*$匹配其余部分直到文本结尾。整个文本由缓冲区\1替换。 (考虑"\\1"中的转义反斜杠。)这对我在cygwin中的bash工作正常,因为我曾经在我的bash初始化中定义了LANG=C(在遇到德语区域设置问题之后)。 Ed Morton(再次)指出使用[[:alpha:]]代替[A-Za-z]应该更加健壮。

    如果您有非GNU awk,则gensub()不可用。 (几个星期前,另一个大师(一个名字中有 k 的大师)告诉我,世界上没有其他的问题,而不是gawks。检查这一点,我意识到即使是awk在我们的公司中,Windows VS构建链实际上是一个傻瓜。然而,自从我了解到这一点后,我偶然发现我的答案没有很好地排除,因为我没有认为解决方案是明确的(或隐含的)非GNU awk所需...)

    所以这是非GNU awk filter4.awk的4 th 版本:

    {
      text = $1
      gsub(/[^[:alpha:]].*$/, "", text)
      if (length(text) > 3) { print $0 }
    }
    

    测试:

    $ awk -f filter4.awk filter2.txt
    Ahoy! : 7
    more : 8
    Hello World : 0
    Hello! World. : 0
    
    $
    

    对于gsub(),我恢复了reg-ex替换的逻辑:从第一个非alpha字符到文本结尾的所有内容都被空字符串替换。 (AFAIK,甚至不存在gsub()中的枚举缓冲区。)

    临时变量text的赋值是必要的,因为gsub()修改了其3 rd 参数的内容。如果我直接提供$1(正如我在修复之前所做的那样),其内容将会更改,而这又会改变$0的内容。