【问题标题】:Compare lines within a file in bash在 bash 中比较文件中的行
【发布时间】:2019-03-15 11:38:06
【问题描述】:

input.txt 文件

12345678,Manoj,23,Developer
12345678,Manoj,34,Developer
12345678,Manoj,67,Developer
12345679,Vijay,12,Tester
12345679,Vijay,98,Tester
12345676,Samrat,100,Manager
12345676,Samrat,25,Manager
12345676,Samrat,28,Manager

所需的输出文件

12345678,Manoj,23,Developer,0
12345678,Manoj,34,Developer,1
12345678,Manoj,67,Developer,2
12345679,Vijay,12,Tester,0
12345679,Vijay,98,Tester,1
12345676,Samrat,100,Manager,0
12345676,Samrat,25,Manager,1
12345676,Samrat,28,Manager,2

说明

这里的第一个值,即我的输入文件前 3 行中的 12345678 是相同的,因此分别在前 3 行附加 ,0 ,1 and ,2。与以下几行类似。

如何在 Shell 脚本中完成。

在所需的输出中编辑

是否也可以将 Desired Output 数字格式更改为以下输出?

12345678,Manoj,23,Developer,0000000
12345678,Manoj,34,Developer,0000001
12345678,Manoj,67,Developer,0000002
12345679,Vijay,12,Tester,0000000
12345679,Vijay,98,Tester,0000001
12345676,Samrat,100,Manager,0000000
12345676,Samrat,25,Manager,0000001
12345676,Samrat,28,Manager,0000002

新功能: 是否可以从 0000019 开始编号。是否有任何其他选项可以初始化像 a=5、a=19、a=39 这样的变量,之后我可以从其中递增。

12345678,Manoj,23,Developer,0000019
12345678,Manoj,34,Developer,0000020
12345678,Manoj,67,Developer,0000021
12345679,Vijay,12,Tester,0000019
12345679,Vijay,98,Tester,0000020
12345676,Samrat,100,Manager,0000019
12345676,Samrat,25,Manager,0000020
12345676,Samrat,28,Manager,0000021

【问题讨论】:

  • 在提供答案或 cmets 后,请勿更改问题的内容。这使得编辑之前的所有答案和 cmets 不再有效。而是编辑您的问题并添加任何添加到您的问题底部。这样答案和 cmets 将保持有效。 (你不知道会得到一个免费赠品,但下次添加:)
  • 注明@DavidC.Rankin

标签: bash shell awk


【解决方案1】:

使用 awk:

$ awk 'BEGIN{FS=OFS=",";RS="\r?\n"}{print $0,a[$1]++}' file

输出:

12345678,Manoj,23,Developer,0
12345678,Manoj,34,Developer,1
12345678,Manoj,67,Developer,2
12345679,Vijay,12,Tester,0
12345679,Vijay,98,Tester,1
12345676,Samrat,100,Manager,0
12345676,Samrat,25,Manager,1
12345676,Samrat,28,Manager,2

编辑

随着需求的变化和大量的评论,这里是最终版本(修订一,因为 cmets 和 OP 的要求不同,敲木头):

$ awk 'BEGIN{FS=","}{sub(/\r$/,"");printf "%s,%07d" ORS,$0,a[$1]++}' file

解释:

$ awk '
BEGIN { 
    FS=","
    # ORS="\r\n"                     # uncomment if Windows line-endings are desired
}      
{
    sub(/\r$/,"")                    # remove Windows line-endings (ie. \r from \r\n)
    printf "%s,%07d" ORS,$0,a[$1]++  # output zeropadded running count on $1
}' file

使用 gawk、mawk、busybox awk 和 original-awk(awk 版本 20121220)进行测试。哦,5 年前回收了我的 Solaris 盒子。 ;D

【讨论】:

  • {printf "%s,%07d\n",$0,a[$1]++}(干得好@JamesBrown)
  • {printf "%s,%07d\n",$0,a++}
  • 我一定会的......詹姆斯
  • 这里有几个 cmets: (1) RS="\r?\n" 的用法不是 POSIX,这仅适用于少数版本的 awk(主要是 gawk)。 (2) dos 文件很可能应该再次成为 dos 文件,目前,行尾将只有“\n”。您可能想使用printfRT 而不是print,后者附加了默认ORS (3) 无需设置FS。 (awk 'BEGIN{RS="\r?\n"}{printf "%s,%0.7d" RT; $0,a[$1]++}' file)
  • @JamesBrown 我知道你大部分都知道,我只是将它作为一般评论写给阅读你答案的人。
【解决方案2】:

更新以修复我以前的自我未知行结尾error

使用这个,将在\r\n\n 行结尾处工作,输出将以\n 结尾:

awk -F, 'sub(/\r$/,"") ($(NF+1)=sprintf("%07d",a[$2]++))' OFS=, input.txt

输出:

12345678,Manoj,23,Developer,0000000
12345678,Manoj,34,Developer,0000001
12345678,Manoj,67,Developer,0000002
12345679,Vijay,12,Tester,0000000
12345679,Vijay,98,Tester,0000001
12345676,Samrat,100,Manager,0000000
12345676,Samrat,25,Manager,0000001
12345676,Samrat,28,Manager,0000002

我这样写是为了简洁,它在功能上等于:

awk 'BEGIN{FS=OFS=","}{sub(/\r$/,"");$(NF+1)=sprintf("%07d",a[$2]++)}1' input.txt

如果您安装了ruby

ruby -aF, -pe 'BEGIN{a=Hash.new(-1)};sub(/\r?$/, "," + "%07d" % a[$F[1]]+=1)' input.txt

同样的输出。

顺便说一句,如果你希望它以 19 开头,你可以使用这个(将 19+ 添加到值中):

awk 'sub(/\r$/,"") ($(NF+1)=sprintf("%07d",19+a[$2]++))' FS=, OFS=, input.txt

或者这个(初始化为18):

ruby -aF, -pe 'BEGIN{a=Hash.new(18)};sub(/\r?$/, "," + "%07d" % a[$F[1]]+=1)' input.txt

这些都使用 $2(第 2 列)作为键,因为在您的示例中 $1$2 是相关的,因此使用其中任何一个都可以。

【讨论】:

    【解决方案3】:

    请您尝试以下操作。(无需编辑行只需按附加数组的计数值打印)

    awk 'BEGIN{FS=OFS=","} {printf("%s,%07d\n",$0,count[$2]++)}' Input_file
    

    【讨论】:

    • @Manoj,您能否告诉我将我的答案删除为正确答案的原因?
    【解决方案4】:

    使用 Perl

    $ cat manoj.txt
    12345678,Manoj,23,Developer
    12345678,Manoj,34,Developer
    12345678,Manoj,67,Developer
    12345679,Vijay,12,Tester
    12345679,Vijay,98,Tester
    12345676,Samrat,100,Manager
    12345676,Samrat,25,Manager
    12345676,Samrat,28,Manager
    $ perl -F, -lane ' $F[$#F]=~s/\r//g; $F[$#F+1]=sprintf("%07d",$kv{$F[0]}++);$,=",";  print @F ' manoj.txt
    12345678,Manoj,23,Developer,0000000
    12345678,Manoj,34,Developer,0000001
    12345678,Manoj,67,Developer,0000002
    12345679,Vijay,12,Tester,0000000
    12345679,Vijay,98,Tester,0000001
    12345676,Samrat,100,Manager,0000000
    12345676,Samrat,25,Manager,0000001
    12345676,Samrat,28,Manager,0000002
    $
    

    【讨论】:

    • 你能解释一下吗?我不知道$kv 变量,谢谢
    猜你喜欢
    • 2018-04-17
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多