【问题标题】:Awk program to compare number of fields by space of each lineawk 程序按每行的空间比较字段数
【发布时间】:2019-02-24 22:45:19
【问题描述】:

我正在尝试检查文件中的每一行是否具有相同的长度(或字段数)。 我正在执行以下操作,但似乎不起作用。

NR==1 {length=NF}

NR>1 && NF!=length {print}

这可以通过单行 awk 完成吗?或者程序很好。

输入样本是:

12 34 54 56
12 89 34 33
12
29 56 42 42

如果它们具有相同数量的字段,我的预期输出将是“是”或“否”。

【问题讨论】:

  • 欢迎来到 SO,你的意思是说你想检查 Input_file 的所有行,看看它们是否都有相同的字段?请您确认一次好吗?您也可以在帖子中提及输入样本和预期输出样本,然后告诉我们?
  • 我想检查所有行,看看它们是否有相同数量的字段。
  • 您的代码会打印出与第一行具有相同字段数的所有行。查看!=exit
  • seems not to work?如果它没有产生语法错误,因为length 是一个函数名,那么你的 awk 坏了,换一个新的。

标签: unix awk


【解决方案1】:

你可以试试这个命令,它检查每行中的字段数并将其与第一行的字段数进行比较:

awk 'NR==1{a=NF; b=0} (NR>1 && NF!=a){print "No"; b=1; exit 1}END{if (b==0) print "Yes"}' test.txt

在字段数与输入的第一行不同的第一行中中止检查。

输入

12 43 43
12 32

你会得到“不”

【讨论】:

    【解决方案2】:

    试试:

    awk 'BEGIN{a="yes"} last!="" && NF!=last{a="no"; exit} {last=NF}  END{print a}' file
    

    工作原理

    • BEGIN{a="yes"}

      这会将变量a 初始化为yes。 (我们假设所有行都具有相同的数字字段,除非另有证明。)

    • last!="" && NF!=last{a="no"; exit}

      如果last已被赋值并且当前行的字段数与上一个不同,则将a设置为no并退出。

    • {last=NF}

      last更新为当前行的字段数。

    • END{print a}

      退出前,打印a

    示例

    $ cat file1
    2 34 54 56
    12 89 34 33
    12
    29 56 42 42
    $ awk 'BEGIN{a="yes"} last!="" && NF!=last{a="no"; exit} {last=NF}  END{print a}' file1
    no
    $ cat file2
    2 34 54 56
    12 89 34 33
    29 56 42 42
    $ awk 'BEGIN{a="yes"} last!="" && NF!=last{a="no"; exit} {last=NF}  END{print a}' file2
    yes
    

    【讨论】:

      【解决方案3】:

      我假设您要检查所有行的字段,如果它们相等或不相等,那么请尝试以下操作。

      awk '
      FNR==1{
        value=NF
        count++
        next
      }
      {
        count=NF==value?++count:count
      }
      END{
        if(count==FNR){
           print "All lines are of same fields"
      }
        else{
           print "All lines are NOT of same fields."
        }
      }
      '  Input_file
      

      附加内容(仅在需要时): 如果您想打印所有行都具有相同字段以及 yesall are same fields in file 的文件内容输出中的消息,然后尝试关注。

      awk '
      {
        val=val?val ORS $0:$0
      }
      FNR==1{
        value=NF
        count++
        next
      }
      {
        count=NF==value?++count:count
      }
      END{
        if(count==FNR){
          print "All lines are of same fields" ORS val
        }
        else{
          print "All lines are NOT of same fields."
        }
      }
      '   Input_file
      

      【讨论】:

      • 这是检查字段数还是字段本身?
      • @OldDUck,它将检查的字段数,也会在几分钟内添加解释。
      • count=NF==value?++count:count 非常神秘。一些空格和括号会有很长的路要走,但是你仍然会在“真正的”腿中有count = ++count,这对于 100% 预测结果来说并不是微不足道的! count += (NF==value ? 1 : 0) 怎么样(如果这是你的代码所做的)?
      【解决方案4】:

      应该这样做

      $ awk 'NR==1{p=NF} p!=NF{s=1; exit} END{print s?"No":"Yes"}' file
      

      但是,如果这将成为工作流程的一部分,则设置退出状态会更好。

      由于等价性具有传递性,所以除了第一行以外不需要保留NF;将0 设置为成功值不需要初始化为默认值。

      【讨论】:

      • 不错。挑剔 - 乍一看,我认为s 的意思是same,所以一开始我被逻辑所迷惑。我本来希望变量名可能是d,而它的意思是different
      • 是的,单字符变量是神秘的,含义应该从上下文中得出。这里我的意思是 status,就像退出脚本时的 status code 一样,如果您将 print ... 更改为 exit s
      • 嗯,我不认为它的意思是status,因为你说however, setting the exit status would be better,所以听起来你没有设置状态,然后你没有退出具体状态。不过你是对的,单个 char 变量可能意味着任何东西,我现在明白你在命名它时的想法 s,谢谢!
      【解决方案5】:

      一个高效的 even fields shell 函数,使用sed 构造一个regex,(基于输入的第一行),提供给GNU grep,它查找字段长度不匹配:

      # Usage: ef filename
      ef() { sed '1s/[^ ]*/[^ ]*/g;q' "$1" | grep -v -m 1 -q -f - "$1" \
             && echo no || echo yes ; }
      

      对于具有不均匀字段的文件grep -m 1 在第一个非均匀行之后退出 -- 所以如果文件有一百万行长,但不匹配发生在第 #2 行,grep 只需要读取两行,不是一百万。另一方面,如果没有不匹配,grep 将不得不读取一百万行。

      【讨论】:

        猜你喜欢
        • 2017-07-09
        • 2018-05-17
        • 2022-01-01
        • 2022-11-01
        • 1970-01-01
        • 2014-12-25
        • 2017-01-26
        • 2011-05-06
        • 2012-05-17
        相关资源
        最近更新 更多