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 / 问题 / 704399
Accepted
Sergio Jimenez
Sergio Jimenez
Asked: 2022-05-31 08:29:51 +0800 CST2022-05-31 08:29:51 +0800 CST 2022-05-31 08:29:51 +0800 CST

为有 6 个字段而不是 7 个字段的记录添加额外字段

  • 772

我对用逗号分隔的文本文件有疑问,当我要开始接收具有混合布局的文件(数百个)时,一些记录将有 7 个字段(总共 6 个逗号)和其他记录在同一个文件中将有 6 个字段(共 5 个逗号)。

当我找到一条包含 5 个逗号的记录时,我想在该记录的末尾添加一个逗号,后跟 NA,因此我的加载过程认为它有 7 个字段,即最后一个 NA。

这就是我现在所拥有的,第一条记录有 7 个字段,第二条只有 6 个:

200000003183000100,Data,NA,0,IN,0,0.00
200000004625000000,Data,NA,0,IN,0

这是我所期望的(两条记录都有 7 个字段)

200000003183000100,Data,NA,0,IN,0,0.00
200000004625000000,Data,NA,0,IN,0,NA

这可以用 sed 或类似的东西计算逗号并在文件末尾添加,NA 只要只有 5 个逗号。请记住,这将发生在数百个文件中,所以我不知道是否需要使用文件名作为参数等等。

text-processing sed
  • 5 5 个回答
  • 302 Views

5 个回答

  • Voted
  1. Gilles Quenot
    2022-05-31T08:35:13+08:002022-05-31T08:35:13+08:00

    如果允许awk :

    awk -F, 'NF==6{$0=$0",NA"}1' file
    
    • 8
  2. Kusalananda
    2022-06-01T03:14:54+08:002022-06-01T03:14:54+08:00

    类似于Gilles Quenot 的 answer,但将新字段添加为新字段而不是当前行末尾的字符串。此外,允许在命令行上配置分隔符和预期的字段数,并将用字符串填充缺失的字段NA:

    $ awk -F , -v nf=7 'BEGIN { OFS = FS } { for (i = NF+1; i <= nf; ++i ) $i = "NA" }; 1' file
    200000003183000100,Data,NA,0,IN,0,0.00
    200000004625000000,Data,NA,0,IN,0,NA
    
    $ awk -F , -v nf=12 'BEGIN { OFS = FS } { for (i = NF+1; i <= nf; ++i ) $i = "NA" }; 1' file
    200000003183000100,Data,NA,0,IN,0,0.00,NA,NA,NA,NA,NA
    200000004625000000,Data,NA,0,IN,0,NA,NA,NA,NA,NA,NA
    

    这显然假设输入是简单的 CSV格式(不包含嵌入逗号或换行符的字段)。

    • 3
  3. schrodingerscatcuriosity
    2022-05-31T09:06:41+08:002022-05-31T09:06:41+08:00

    与sed:

    $ sed -E '/^([^,]+,){5}[^,]+$/s/$/,NA/' file 
    200000003183000100,Data,NA,0,IN,0,0.00
    200000004625000000,Data,NA,0,IN,0,NA
    
    • 2
  4. guest_7
    2022-05-31T09:36:48+08:002022-05-31T09:36:48+08:00

    Posix sed,我们尝试更改第 6 个逗号,如果成功,我们打印并返回读取下一条记录(测试命令t)否则,将,NA字符串附加到当前记录的末尾。

    sed '
      s/,/,/6;t
      s/$/,NA/
    ' file
    

    使用awk,一种方法是:

    awk '/(.*,){6}/ || sub(/$/,",NA")' file
    

    当您需要对多个文件执行此操作时的用例是通过find命令。

    假设您的 CSV 文件已命名*.csv

    find . -type f -name '*.csv' -exec \
      sed -i 's/,/,/6;t' -e 's/$/,NA' {} +
    

    对于 awk,如果您的 awk 支持,请使用 inplace 选项(GNU awk 版本 4.1.0 以上)

    find . -type f -name "*.csv" -exec \
    awk -i inplace '!/(.*,){6}/{$0=$0",NA"}1' {} +
    

    符号{} +将多个文件名汇集到 awk 或 sed 命令行,以便最小化这些实用程序的调用

    笔记:

    • 该文件有 5 个或 6 个逗号。
    • 字段本身不能包含逗号。
    • 行尾是 linux 样式 (\n)。
    • 2
  5. Best Answer
    Ed Morton
    2022-06-02T04:41:42+08:002022-06-02T04:41:42+08:00

    为了提高 awk 的效率,除非必须,否则不要修改记录 ( $0) 或字段 ( $1,等)。$2这不会修改它们中的任何一个:

    awk -F, '{print $0 (NF==6 ? ",NA" : "")}'
    

    其他现有的 awk 答案要么修改 $0 要么修改字段,其中任何一个都会减慢处理速度。

    这些直接更改 $0 (因此间接添加一个字段):

    awk -F, 'NF==6{$0=$0",NA"}1'
    awk '/(.*,){6}/ || sub(/$/,",NA")'
    awk '!/(.*,){6}/{$0=$0",NA"}1'
    

    这需要 awk 找到新的内存以便$0移动,因为它的大小增加了(连接或以其他方式更改变量的大小是 awk 中最慢的操作之一)并导致 awk 重新拆分$0为字段。

    这些直接更改字段(因此间接更改 $0):

    awk -F, -v nf=7 'BEGIN { OFS = FS } (NF < nf){ $(nf)="N/A"}1'
    awk -F, -v nf=7 'BEGIN { OFS = FS } { for (i = NF+1; i <= nf; ++i ) $i = "NA" }; 1'
    

    这会导致 awk 从它的字段中重建,并且由于它的大小增加$0,再次需要 awk 找到要移动的新内存$0

    要使用 GNU awk 在数百个(但少于 ARG_MAX 的)CSV 文件上运行任何 awk 脚本,只需:

    awk -i inplace 'script' file*.csv
    

    或使用任何 awk:

    tmp=$(mktemp)
    for file in file*.csv; do
        awk 'script' "$file" > "$tmp" &&
        mv -- "$tmp" "$file"
    done
    
    • 2

相关问题

  • 如何删除两行之间的单行

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

  • 在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