在文本文件中,一列中有一个数字序列,后跟一个短字符串。这是示例文件中“名称”下的第5列:
SESSION NAME: session
SAMPLE RATE: 48000.000000
BIT DEPTH: 16-bit
SESSION START TIMECODE: 00:00:00:00.00
TIMECODE FORMAT: 24 Frame
# OF AUDIO TRACKS: 2
# OF AUDIO CLIPS: 2
# OF AUDIO FILES: 2
M A R K E R S L I S T I N G
# LOCATION TIME REFERENCE UNITS NAME COMMENTS
2 0:00.500 24000 Samples xxxx0001
3 0:03.541 170000 Samples xxxx0002
4 0:05.863 281458 Samples xxxx0003
5 0:08.925 428430 Samples xxxx0004
6 0:10.604 509025 Samples xxxx0005
7 0:13.973 670742 Samples xxxx0006
8 0:15.592 748453 Samples xxxx0008
9 0:19.243 923666 Samples xxxx0008
在上面的示例中,缺少0007,并且复制了0008。
因此,我希望能够检查数字是否为
- 给定列中当前存在的范围。
- 是否有重复项
我还要输出以下结果:
SKIPPED:
xxxx0007
DUPLICATES:
xxxx0008
我能获得的最远的结果是使用awk
来获得我需要的列:
cat <file.txt> | awk '{ print $5 }'
这让我明白了
NAME
xxxx0001
xxxx0002
xxxx0003
xxxx0004
xxxx0005
xxxx0006
xxxx0008
xxxx0008
但是我不知道从这里去哪里。
我是否需要遍历列表项并进行解析,以便仅获取数字,然后开始对下一行进行一些比较?
任何帮助将不胜感激 谢谢!
答案 0 :(得分:2)
作为起点,请尝试以下操作:
awk '
NR>1 { gsub("[^0-9]", "", $5); count[$5]++ }
END {
print "Skipped:"
for (i=1; i<NR; i++)
if (count[i] == 0) printf "xxxx%04d\n", i
print "Duplicates:"
for (i=1; i<NR; i++)
if (count[i] > 1) printf "xxxx%04d\n", i
} ' file.txt
输出:
Skipped:
xxxx0007
Duplicates:
xxxx0008
NR>1
用于跳过顶部标题行。gsub("[^0-9]", "", $5)
从$5
中删除非数字字符。
结果,$5
被设置为从第5列提取的数字。count[]
计算每个数字的出现次数。如果值
是0
(或未定义),表示该数字被跳过。如果值
大于1
,则数字重复。END { ... }
块在所有输入行处理完毕后 执行
并报告最终结果非常有用。但是,“跳过/重复”方法不能很好地检测到以下情况:
# LOCATION TIME REFERENCE UNITS NAME COMMENTS
1 0:00.500 24000 Samples xxxx0001
2 0:02.888 138652 Samples xxxx0003
3 0:04.759 228446 Samples xxxx0004
4 0:07.050 338446 Samples xxxx0005
5 0:09.034 433672 Samples xxxx0006
6 0:12.061 578958 Samples xxxx0007
7 0:14.111 677333 Samples xxxx0008
8 0:17.253 828181 Samples xxxx0009
或
# LOCATION TIME REFERENCE UNITS NAME COMMENTS
1 0:00.500 24000 Samples xxxx0001
2 0:02.888 138652 Samples xxxx0003
3 0:04.759 228446 Samples xxxx0002
4 0:07.050 338446 Samples xxxx0004
5 0:09.034 433672 Samples xxxx0005
6 0:12.061 578958 Samples xxxx0006
7 0:14.111 677333 Samples xxxx0007
8 0:17.253 828181 Samples xxxx0008
最好在期望值和实际值之间进行逐行比较。那怎么样:
awk '
NR>1 {
gsub("[^0-9]", "", $5)
if ($5 != NR-1) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-1, $5
} ' file.txt
原始示例的输出:
Line: 8 Expected: xxxx0007 Actual: xxxx0008
[编辑]
根据修订后的输入文件(其中包含更多额外的标题行),如何操作:
awk '
f {
gsub("[^0-9]", "", $5)
if ($5 != NR-skip) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-skip, $5
}
/^#[[:blank:]]+LOCATION[[:blank:]]+TIME REFERENCE/ {
skip = NR
f = 1
}
' file.txt
输出:
Line: 19 Expected: xxxx0007 Actual: xxxx0008
上面的脚本跳过这些行,直到找到特定的模式# LOCATION TIME REFERENCE
。
f { ... }
为true,则执行f
块。因此跳过该块
直到f
设置为非零值。/^# .../ { ... }
块匹配,
图案。如果找到skip
,则将其设置为标题行的数量,并且
f
(标志)设置为1,因此从下一个执行上一个块
迭代。 希望这会有所帮助。