我有一个类似于下面的数据集。
并且我需要用"|“之前的值与实际行匹配的特定行之前/之后的行的相同值来完成”|“之后的每一行。
如果能用bash/shell脚本或excel来完成这项工作,我会非常感激。
10166_101|
10166_101|50
10296_5|
10296_5|50
10484_5|20
10484_5|
10692_7|
10692_7|10
10742_102|
10742_102|100
10742_102|
10767_13|
10767_13|30
10793_9|
10793_9|50
10863_8|40
10863_8|
10887_3|
10887_3|40
10929_2|24
11004_2|10
11151_5|
11151_5|20
11212_21|80
11447_6|30
11486_9|
11486_9|80
11510_105|20
11510_105|
11610_3|
11610_3|10
11635_7|20
11635_7|因此,数据将如下所示:
10166_101|50
10166_101|50
10296_5|50
10296_5|50
10484_5|20
10484_5|20
10692_7|10
10692_7|10
10742_102|100
10742_102|100
10742_102|100
10767_13|30
10767_13|30
10793_9|50
10793_9|50
10863_8|40
10863_8|40
10887_3|40
10887_3|40
10929_2|24
11004_2|10
11151_5|20
11151_5|20
11212_21|80
11447_6|30
11486_9|80
11486_9|80
11510_105|20
11510_105|20
11610_3|10
11610_3|10
11635_7|20
11635_7|20 发布于 2020-02-24 10:09:06
#!/bin/sh
sort --reverse inputfile > /tmp/reversedinput
awk -F\| '$0=="" {next}
$2!="" {line=$0;print line}
$2=="" {print line;}' /tmp/reversedinput > /tmp/reversedoutput
sort /tmp/reversedoutput > outputfile它怎麽工作?
这将对您的inputfile进行反向排序,使其成为/tmp/reversedinput
11635_7|20
11635_7|
11610_3|10
11610_3|
11510_105|20
11510_105|
...现在,逐行读取文件(从顶部开始),如果当前迭代中的行在管道字符之后没有任何内容,只需将其替换为上面的行。这就是awk片段正在做的事情。所以你得到了/tmp/reversedoutput。
最后,只需按正确的顺序对其进行排序,就可以得到outputfile。
发布于 2020-02-24 10:52:47
试试这个awk脚本:
awk -F"|" -v OFS="|" '
NR == FNR { if ($2) values[$1] = $2 ; next }
{ print $1 , values[$1] }
' $1 $1 上面,$1被认为是脚本的参数-它应该是输入文件的文件名。我将该文件传递给awk两次,$1 $1让awk解析该文件两次。awk第一次读取文件时,表达式NR == FNR为true。也就是说,当前记录号(NR)与当前文件中的记录号相同。无论如何,我们只是记住了值散列中的值。
Awk再次遍历文件,打印每一行与其相关联的值。
发布于 2020-02-24 10:58:09
这个excel函数将解决这个问题,只需将“输入”粘贴到单元格A2中,然后在单元格B2中使用此函数,然后向下填充,直到您到达B34 (在本例中)。
=IF(LEN(A2)=FIND("|",A2),
IF(MID(A2,1,FIND("|",A2))=IFERROR(MID(A1,1,FIND("|",A1)),""),
MID(A2,1,FIND("|",A2))&MID(A1,FIND("|",A1)+1,99),
IF(MID(A2,1,FIND("|",A2))=MID(A3,1,FIND("|",A3)),
MID(A2,1,FIND("|",A2))&MID(A3,FIND("|",A3)+1,99),
A2)),
A2)它怎麽工作?
它首先检查字符串是否需要修改:
LEN(A2)=FIND("|",A2)如果是,则将字符串的前半部分与前一行进行比较:
IF(MID(A2,1,FIND("|",A2))=IFERROR(MID(A1,1,FIND("|",A1)),"")`注意:"IFERROR“用于处理第一行的情况,因为MID函数将返回#Value
如果匹配,则将当前字符串的前半部分与先前的字符串后半部分合并(这可能有些过分,因为这两行应该是相同的)。
MID(A2,1,FIND("|",A2))&MID(A1,FIND("|",A1)+1,99)输出:
10166_101|50
10166_101|50
10296_5|50
10296_5|50
10484_5|20
10484_5|20
10692_7|10
10692_7|10
10742_102|100
10742_102|100
10742_102|100
10767_13|30
10767_13|30
10793_9|50
10793_9|50
10863_8|40
10863_8|40
10887_3|40
10887_3|40
10929_2|24
11004_2|10
11151_5|20
11151_5|20
11212_21|80
11447_6|30
11486_9|80
11486_9|80
11510_105|20
11510_105|20
11610_3|10
11610_3|10
11635_7|20
11635_7|20https://stackoverflow.com/questions/60368271
复制相似问题