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 / 问题 / 791883
Accepted
Ismael Sanchez
Ismael Sanchez
Asked: 2025-03-03 10:21:30 +0800 CST2025-03-03 10:21:30 +0800 CST 2025-03-03 10:21:30 +0800 CST

如何计算 Unix 中分隔文件中的空白字段

  • 772

来自以下脚本:

EmpID:Name:Designation:UnitName:Location:DateofJoining:Salary
1001:Thomson:SE:IVS:Mumbai:10-Feb-1999:60000
1002:Johnson:TE::Bangalore:18-Jun-2000:50000
1003:Jackson:DM:IMS:Hyderabad:23-Apr-1985:90000
1004:BobGL::ETA:Mumbai:05-Jan-2004:55000
1005:Alice:PA:::26-Aug-2014:25000
1006:LilySE::IVS:Bangalore:17-Dec-2015:40000
1007:Kirsten:PM:IMS:Mumbai:26-Aug-2014:45000
1004:BobGL::ETA:Mumbai:05-Jan-2021:55000

我想获取空格数(以 '::' 表示)。非常感谢您的支持。

command-line
  • 5 5 个回答
  • 98 Views

5 个回答

  • Voted
  1. Kusalananda
    2025-03-03T14:47:30+08:002025-03-03T14:47:30+08:00

    假设您想要计算冒号分隔的 CSV 文件中空字段的数量,我们可以使用Miller ( mlr)进行操作,如下所示:

    $ mlr --csv --ifs colon put -q 'for (k,v in $*) { is_empty(v) { @count=@count+1 } } end { print @count }' file
    6
    

    由于 Miller 支持 CSV,因此它也能正确处理包含嵌入冒号的字段。例如,以下 CSV 有两个空字段(Designation和Salary):

    EmpID:Name:Designation:UnitName:Location:DateofJoining:Salary
    1008:"Text::CSV"::"Team::Overseas":Stockholm:2025-03-03:
    
    • 3
  2. Best Answer
    Fravadona
    2025-03-03T23:03:02+08:002025-03-03T23:03:02+08:00

    你可以链接一些标准实用程序:

    编辑:感谢@Kusalananda 提醒我们grep -c使用grep | wc -l

    <file.txt tr ':' '\n' | grep -c '^$'
    

    或使用awk:

    <file.txt awk -F: '{for (i=1; i<=NF; i++) n+=($i=="")} END {print n}'
    

    也就是说,只要输入字段不包含任何LF或:字符。

    • 1
  3. Schmaehgrunza
    2025-03-03T10:53:36+08:002025-03-03T10:53:36+08:00

    您想要一个纯 bash 解决方案吗?

    awk 示例,它是 POSIX!

    awk 'BEGIN { counter=0; } { text=$0; while (spaceI=index(text,"::")) { text=substr(text,spaceI+2); counter++; }} END { print counter; }' < your_file
    

    或者

    echo - n 'EmpID:Name:Designation:UnitName:Location:DateofJoining:Salary
    1001:Thomson:SE:IVS:Mumbai:10-Feb-1999:60000
    1002:Johnson:TE::Bangalore:18-Jun-2000:50000
    1003:Jackson:DM:IMS:Hyderabad:23-Apr-1985:90000
    1004:BobGL::ETA:Mumbai:05-Jan-2004:55000
    1005:Alice:PA:::26-Aug-2014:25000
    1006:LilySE::IVS:Bangalore:17-Dec-2015:40000
    1007:Kirsten:PM:IMS:Mumbai:26-Aug-2014:45000
    1004:BobGL::ETA:Mumbai:05-Jan-2021:55000' | awk 'BEGIN { counter=0; } { text=$0; while (spaceI=index(text,"::")) { text=substr(text,spaceI+2); counter++; }} END { print counter; }'
    

    重击:

    { counter=0; while IFS= read -r line; do doIT=1; while ((doIT > 0)); do line_L=${#line}; line=${line#*::}; if ((line_L > ${#line})); then ((counter++)); else doIT=0; fi; done; done; echo -n "$counter" ; } < your_file
    
    • 0
  4. David G.
    2025-03-03T11:46:00+08:002025-03-03T11:46:00+08:00

    这里有一个sed和wc实现,以及一个纯bash实现,以及调用两者的示例代码。我推荐前者。

    #!/bin/bash
    
    sedwc() {
        local v=( $( sed <$1 -e 's/^/:/;s/$/:/;s/[^:][^:]*/x/g;s/::/:y:/g;s/::/:y:/g;s/[x:]//g' | wc ) )
        echo $(( ${v[2]} - ${v[0]} ))
    }
    
    purebash() {
        local line count=0 mod
        while read line
        do
            while true
            do
                mod="${line/::/:}"
                [[ "$line" = "$mod" ]] && break
                : $(( count++ ))
                line="$mod"
            done
        done <"$1"
        echo $count
    }
    
    a=$( sedwc sample )
    b=$( purebash sample )
    
    echo sedwc = "$a" purebash = "$b"
    

    您的输入格式暗示但您没有指定的一件事是,行首和行末可能会有空白条目。sedwc 实现通过在每行的开头和结尾添加一个额外的冒号来处理这些空白。如果这些空白不应计算在内,您可以删除文本s/^/:/;s/$/:/;。

    我认为值得解释一下其sed wc实现方式:

    命令 意义 示例内容
    1005:爱丽丝:PA:::2014 年 8 月 26 日:25000
    s/^/:/; 添加额外的前导 :,以捕获第一个字段为空的情况 :1005:爱丽丝:PA:::2014 年 8 月 26 日:25000
    s/$/:/; 添加额外的尾随 :,以捕获最后一个空字段 :1005:爱丽丝:PA:::2014 年 8 月 26 日:25000:
    s/[^:][^:]*/x/g; 将所有非空字段的主体更改为“x” :x:x:x:x:x:x:
    s/::/:y:/g; 将其他所有空白字段更改为包含“y” :x:x:x:y::x:x:
    s/::/:y:/g; 将其他空白字段更改为包含“y” :x:x:x:y:y:x:x:
    s/[x:]//g 消除所有“x”和“:”值,只留下“y”。 年年

    wc然后输出总行数、总字数和总字符数。这可解释为:总记录数、包含任何空白的记录数以及总记录数加总空白数。然后进行一些简单的数学运算,输出总空白数。

    • 0
  5. jubilatious1
    2025-03-03T14:39:39+08:002025-03-03T14:39:39+08:00

    使用Raku(以前称为 Perl_6)

    ~$ BEGIN my $i; m:overlap/ [ ^ ":" || "::" || ":" $ ] { ++$i } /; END say $i;'    file
    

    Raku 是 Perl 家族中的一种编程语言,如果您处理 Unicode/UTF-8 文件,它是一个不错的选择。

    上面我们在命令行中使用类似 awk 的-ne非自动打印逐行标志调用 Raku。我们BEGIN通过声明一个计数器变量来实现$i。为了确保正确计数相邻的冒号,我们使用:overlap修饰符 (named-argument)。

    示例输入:

    EmpID:Name:Designation:UnitName:Location:DateofJoining:Salary
    1001:Thomson:SE:IVS:Mumbai:10-Feb-1999:60000
    1002:Johnson:TE::Bangalore:18-Jun-2000:50000
    1003:Jackson:DM:IMS:Hyderabad:23-Apr-1985:90000
    1004:BobGL::ETA:Mumbai:05-Jan-2004:55000
    1005:Alice:PA:::26-Aug-2014:25000
    1006:LilySE::IVS:Bangalore:17-Dec-2015:40000
    1007:Kirsten:PM:IMS:Mumbai:26-Aug-2014:45000
    1004:BobGL::ETA:Mumbai:05-Jan-2021:55000
    

    示例输出:6

    如果您想查看匹配项,只需添加一个say调用,++$并=>提供行号:

    ~$ raku -ne 'BEGIN my $i; say ++$, " => ",  m:overlap/ [ ^ ":" || "::" || ":" $ ] { ++$i } /; END say "total blank fields: $i";'  file
    1 => ()
    2 => ()
    3 => (「::」)
    4 => ()
    5 => (「::」)
    6 => (「::」 「::」)
    7 => (「::」)
    8 => ()
    9 => (「::」)
    total blank fields: 6
    

    https://raku.org

    • 0

相关问题

  • ip 命令是否支持通配符?

  • 需要许多参数的实用程序的推荐界面是什么?[关闭]

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • 使 mysql CLI 以交互方式向我询问密码

  • 没有服务器的命令行 pub/sub?

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