Sorting 是否删除具有特定列长度的行?

Sorting 是否删除具有特定列长度的行?,sorting,awk,sed,string-length,Sorting,Awk,Sed,String Length,我有一个如下所示的文本文件: A : 1 Boy : 3 Ahoy! : 7 more : 8 Ahoy! : 7 more : 8 我必须删除长度小于或等于3个字母的行。输出应如下所示: A : 1 Boy : 3 Ahoy! : 7 more : 8 Ahoy! : 7 more : 8 感谢这篇文章有点不具体,(由于沟通),根据我对问题的解释,有一些可能的解决方案 我的第一个脚本filter.awk: $3 <= 3 { next } { print $0 } { te

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

A : 1
Boy : 3
Ahoy! : 7
more : 8
Ahoy! : 7
more : 8
我必须删除长度小于或等于3个字母的行。输出应如下所示:

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

感谢这篇文章有点不具体,(由于沟通),根据我对问题的解释,有一些可能的解决方案

我的第一个脚本
filter.awk

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

埃德·莫顿指出,这可以做得更短:

$3 > 3
这对我来说也是新的。(可能是这样,我被lex搞糊涂了,它的工作方式正好相反:在lex/flex中,所有不匹配的东西都会被重复。)

更可靠的方法是使用冒号(
)作为列分隔符(或者类似于在awk:field separator中命名的冒号)。可以通过指定内置变量
FS
来更改字段分隔符。这可以通过使用命令行参数
-F
或在一个特殊的
开始
规则中赋值来完成,该规则始终在开始时执行。(我更喜欢这封信使脚本“独立”

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

测试:

对OP的另一种解释可能是考虑每行第一列中的连续字母数。为此,一些内置功能开始发挥作用:

  • gensub()
    一个功能强大的替换函数,不幸的是,它只在GNU awk中可用

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

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

    A : 1
    Boy : 3
    Ahoy! : 7
    more : 8
    
    A : 1
    Boy : 3
    Ahoy! : 7
    more : 8
    Hello World : 0
    Hello! World. : 0
    Hi World : 0
    
    filter3.awk
    (即
    filter.awk
    V3.0):

    测试:

    由于在这种情况下字段分隔符不变,因此第一个字段由字符组成,直到第一个空格。模式
    (^[A-Za-z]+)
    捕获文本开头的所有字母,并将它们存储到第一个内部缓冲区中。
    *$
    匹配其余部分,直到文本结束。整个文本将替换为缓冲区
    \1
    。(考虑一下
    “\\1”
    中转义的反斜杠)这在cygwin中的bash上运行良好,因为我曾经在bash初始化中定义过
    LANG=C
    (在遇到德语区域设置问题之后)。Ed Morton(再次)指出,使用
    [[:alpha:]
    而不是
    [A-Za-z]
    应该更健壮

    如果您有非GNU awk,则
    gensub()
    不可用。(几周前,另一位大师(他的名声是k)告诉我,世界上没有什么比在世界上呆头呆脑的了。检查到这一点,我意识到即使是我们公司的WWS VS构建链中的AWK实际上是一种呆滞。然而,自从我学会了这一点之后,我多次绊倒了,因为我没有认为解决方案是显而易见的,所以我的答案并不是很好。非GNU awk需要(或隐含地…)

    这是我为非GNU awk
    filter4.awk提供的第四个版本:

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

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


    临时变量
    text
    的赋值是必要的,因为
    gsub()
    修改其第三个参数的内容。如果我直接提供了
    $1
    (正如我在修复它之前所做的那样),它的内容将会改变,这反过来也会改变
    $0

    的内容,比如
    awk'length($1)>3'
    ?您可以使用类似于
    awk-F:'$2>3'的内容,这里我假设冒号后面的数字就是值,你想继续过滤。你想过滤少于4个,因为示例输出中缺少Boy行。当您说
    长度小于3个字母时
    是指
    长度小于3个字符
    还是
    包含少于3个字母字符
    包含少于3个连续字母字符
    还是其他?你是指整行还是仅在第一个字段中(在
    之前)或其他内容?投入更多的精力提供样本输入/输出,以真正证明您正试图解决的问题-目前,您的输入和输出之间存在太多可能的相关性,无法提供太多帮助。“男孩”有3个字母长,不少于3个,那你为什么要删除它呢?
    $33
    ,但无论如何,我不认为这是OP想要的。wrt
    gensub(/(^[A-Za-z]+).$/,“\\1”,“g”,“$1)
    -1)你应该提到的是特定于呆呆的和更新的mawk,2)字符列表依赖于语言环境,使用
    [:alpha:]
    ,3)您不能多次匹配
    ^
    ,因此第三个参数应该是
    1
    ,而不是
    “g”
    。我仍然不知道代码实现的是否是OP想要的,当然,因为她还没有告诉我们:-)。
    $ awk -f filter3.awk filter2.txt
    Ahoy! : 7
    more : 8
    Hello World : 0
    Hello! World. : 0
    
    $
    
    {
      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
    
    $