AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 557611
Accepted
Johnny Tam
Johnny Tam
Asked: 2019-12-17 18:57:52 +0800 CST2019-12-17 18:57:52 +0800 CST 2019-12-17 18:57:52 +0800 CST

使用 awk 删除第一行上为“-”的列

  • 772

我有桌子

M       -       A       A       -
-       A       G       -       -
M       -       -       -       G

我想执行:如果第一行的任何列包含“-”,则跳过打印该列

预期的输出是

M       A       A 
-       G       - 
M       -       - 

我尝试过这样的事情,但没有奏效

awk 'NR==1 && $i!="-" {print $i}'

有谁知道如何更正命令?

awk text-processing
  • 5 5 个回答
  • 377 Views

5 个回答

  • Voted
  1. Ed Morton
    2019-12-18T11:25:53+08:002019-12-18T11:25:53+08:00
    $ cat tst.awk
    NR == 1 {
        for (i=1; i<=NF; i++) {
            if ($i != "-") {
                f[++numOutFlds] = i
            }
        }
    }
    {
        for (i=1; i<=numOutFlds; i++) {
            printf "%s%s", $(f[i]), (i<numOutFlds ? OFS : ORS)
        }
    }
    
    $ awk -f tst.awk file
    M A A
    - G -
    M - -
    
    • 3
  2. Best Answer
    Kusalananda
    2019-12-18T11:39:28+08:002019-12-18T11:39:28+08:00

    Ed Morton 答案的变体,它通过字段编号记住哪些字段不在-第一行,然后根据数组中保存的索引重新形成输入中的每个记录,out然后打印新记录:

    FNR == 1 {
        for (i = 1; i <= NF; ++i)
            if ($i != "-") out[++nf] = i
    }
    
    {
        for (i = 1; i <= nf; ++i)
            a[i] = $(out[i])
    
        $0 = ""
    
        for (i = 1; i <= nf; ++i)
            $i = a[i]
    
        print
    }
    

    在这里,我牺牲了一些效率来提高可读性,方法是在单独的循环中重建记录,而不是在第二个块的单个循环中打印所需的字段。

    测试:

    $ awk -f script.awk file
    M A A
    - G -
    M - -
    

    使用制表符作为输出字段分隔符运行:

    $ awk -v OFS='\t' -f script.awk file
    M       A       A
    -       G       -
    M       -       -
    

    取决于制表符分隔的输入数据的稍长的单行:

    $ cut -f "$(awk -v OFS=',' '{ nf=split($0,a); $0=""; for (i=1; i<=nf; ++i) if (a[i]!="-") $(++NF)=i; print; exit }' file)" file
    M       A       A
    -       G       -
    M       -       -
    

    这用于将不在第一行的字段编号awk输出为逗号分隔的列表。然后将该列表移交给文件中数据的实际输出。请注意,文件名(这里简称为 )在命令行中给出了两次,一次是 for ,然后是.-cut -ffileawkcut

    • 3
  3. dave_thompson_085
    2019-12-18T00:49:33+08:002019-12-18T00:49:33+08:00

    awk隐式循环输入记录(行)和文件,但不是您必须明确执行的字段。在您的情况下,您需要遍历第一行(标题)中的字段以决定要包含哪些列,然后遍历每一行(标题和非标题)中的字段以在该行中包含所需的列。

    您不清楚是否要查找等于(字符串)“-”或可能将其作为(子)字符串的标题字段。我还假设您有(所有)单个选项卡作为字段分隔符,而不是多个空格,这会更乏味(并且无法从您的帖子中直观区分)。

    awk -F"\t" 'NR==1{for(i=1;i<=NF;i++)s[i]=$i!="-"} {x="";for(i=1;i<=NF;i++)if(s[i])x=x FS $i;print substr(x,2)}'
    # for _matches_ "-" instead of _equals_ "-" change $i!="-" to $i!~/-/
    # note if a nonheader line has more fields than the header did,
    # all extra fields are nonselected (as if their header field was/matched -)
    
    # or (re)use the flags for both what to include _and_ when to terminate the line
    awk -F"\t" 'NR==1{t=RS;for(i=NF;i;i--)if(s[i]=($i!="-"?t:""))t=FS} {for(i=1;i<=NF;i++)if(s[i])printf "%s%s",$i,s[i]}'
    # some people may consider this too clever
    
    • 1
  4. Rakesh Sharma
    2019-12-18T15:43:48+08:002019-12-18T15:43:48+08:00

    使用 Perl。

    对于第一行,构建一个字段为非破折号的索引数组@A。

    然后对于所有行,包括第一行,只打印@F索引在 中的那些字段@A。

    $ perl -lane '$, = "\t";
        $. == 1 and @A = grep $F[$_] ne "-", 0..$#F;
        print @F[@A];
    ' file
    

    输出:

    M   A   A
    -   G   -
    M   -   -
    
    • 0
  5. Rakesh Sharma
    2019-12-18T20:36:04+08:002019-12-18T20:36:04+08:00

    我们可以sed使用backslashitis.

    方法是从第一行创建地图。要保留的字段映射为 x 其他作为破折号。将此地图保存在货舱中。

    然后对于所有行,附加此地图并在 BOL 处放置一个标记。

    在循环中,如果我们看到 \n- 并且将标记前进到下一个字段,我们会继续删除当前行的前导字段。

    当此标记与当前行和保持空间之间的换行符冲突时,循环结束(由于 G 命令)。

    $ sed -Ee '
        1{
          h
          y/-/\n/
          s/\S+/x/g;s/[[:blank:]]+//g
          y/\n/-/
          x
        }
    
        G;s/^/\n/
    
        :a
          s/\n(\S+\s*)(.*\n)x/\1\n\2/
          s/\n(\S+\s*)(.*\n)-/\n\2/
        /\n\n/!ba
    
        s/\s+$//
    ' file
    

    结果

    M       A       A
    -       G       -
    M       -       -
    
    • 0

相关问题

  • 重新排列字母并比较两个单词

  • 在awk中的两行之间减去相同的列

  • 多行文件洗牌

  • 如何更改字符大小写(从小到大,反之亦然)?同时[重复]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve