>场景 1
仅当第 1 列CR
且第 3 列具有重复的行/值时,我才需要执行以下更改。此输入文件可以包含第 3 列的重复行中的 100 行
第 3 列中的值为后缀,序列从a
开始,后跟CR
。
如果我们在 CR like(aCR, bCR, cCR
直到zCR
(附加了 a 到z
的后缀,那么下一个后缀将为第 3 列aaCR, abCR, acCR
依此类推
输入文件
a||c
CR||2157237496
CR||2157237496
CR||2157237496
INV||2157237496
RNV||3457634589
输出文件
a||c
CR||2157237496aCR
CR||2157237496bCR
CR||2157237496cCR
INV||2157237496
RNV||3457634589
场景 2
需要在单独的代码中执行此操作。下面是不同的文件。仅当第 1 列为 DR 且第 3 列具有重复的行/值时,我才需要执行以下更改。第 3 列中的值为后缀,序列从a
开始,但第一个文档后跟DR
除外。
如果我们用 DR like(aDR, bDR, cDR
直到zDR
(附加了后缀直到 a 到z
,那么下一个后缀将在第 3 列中aaDR, abDR, acDR
和依此类推
输入文件
a||c
DR||3770022521
DR||3770022521
DR||3770022521
INV||9876543738
输出文件
a||c
DR||3770022521
DR||3770022521aDR
DR||3770022521bDR
INV||9876543738
我尝试了下面的代码,它为我提供了场景 2 的输出,但无法将序列号附加到第 3 列。我只能a
静态后缀。 这里需要考虑第 1 列等于场景 1 的CR
和场景 2 的DR
(我无法做到(
awk -F"|" -v OFS="|" '{if(++a[$3]>1)$3=$3"a"}1' d1.txt
代码输出:
a||c
CR||2157237496
CR||2157237496a
CR||2157237496a
INV||2157237496a
RNV||3457634589
我需要分别实现方案 1 和 2
编辑:当@Inian握住我的手并重新向我朗读OP时,我编辑了脚本以实际支持重复项。首先,更好的测试数据:
a||c
CR||2157237496
CR||2157237497
CR||2157237496
CR||2157237497
INV||2157237496
RNV||3457634589
场景 1 的尴尬:
$ awk '
BEGIN {
FS=OFS="|" # field delimiters
ab="zabcdefghijklmnopqrstuvwxy" # mod safe alphabet
d=26 # size of alphabet
}
function i2ab(n, b) { # b is local var
while(n>=1) {
p=n%d # this is the letter position
n=n/d # n for the next round
n-=(n==int(n)) # fix for n%d==0 else 26 -> az, not z
b=substr(ab,p+1,1) b # prepend the next letter to buffer
}
return b # return buffer
}
$1=="CR" { # for DR change CR to DR and ++a[$3] to a[$3]++ below
$3=$3 i2ab(++a[$3]) $1 # increment c and map it to a string
}1' file # output
a||c
CR||2157237496aCR
CR||2157237497aCR
CR||2157237496bCR
CR||2157237497bCR
INV||2157237496
RNV||3457634589
请参阅注释以将其更改为方案 2。
该函数i2ab
还提供 26 之后的字母组合:
$ awk '
BEGIN {
ab="zabcdefghijklmnopqrstuvwxy"
d=26
print i2ab(27) # I AM HERE 26 -> z, 27 ->aa
}
function i2ab(n, b) { #
while(n>=1) { #
p=n%d #
n=n/d #
n-=(n==int(n)) #
b=substr(ab,p+1,1) b #####
} ###
return b #
}'
aa # I DID THIS
我可以提供一种解决第一种情况的方法,您可以使用该方法进行扩展以使第二种情况也起作用。它涉及文件的两次解析,但仅在第二次传递时对所选列进行分析。如果答案能够一次性完成,我将兴高采烈地删除答案。
步骤
- 创建函数以根据需要使用带有 ASCII 代码的
sprintf()
从a-z
生成字母字符 - 在第一次传递时,为第三列中包含的值创建一个哈希映射,将第一列中的值作为
CR
- 再次对这些列进行第二次传递时,修改
$3
以生成所需的模式。
脚本应如下所示。将其命名为script.awk
#!/usr/bin/env awk
function generateAlphabets() {
idx = 0
for(i=97;i<123;i++ ) {
letters[idx++]=sprintf("%c",i)
}
}
BEGIN {
generateAlphabets()
FS=OFS="|"
counter=0
}
$1 == "CR" {
map[$1""$3]
}
FNR == NR { next }
($1""$3 in map) {
$3 = $3""letters[counter++]"CR"
}1
运行下面的脚本,如下所示
awk -f script.awk file file
您可以通过放置一个awk
变量来传递CR
或DR
,并在适用的情况下将字符串替换为代码中的变量