通过命令行检查列中的数字是否连续
Check to see if numbers in a column are sequential via command line
在一个文本文件中,我在一列中有一个数字序列,前面有一个短字符串。这是此处示例文件中的第 5 列 "NAME":
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 重复。
因此,我希望能够检查数字是否为:
- sequential given the range that presently exists in the column.
- if there are any duplicates
我也想输出这些结果:
SKIPPED:
xxxx0007
DUPLICATES:
xxxx0008
我能得到的最远的是使用awk
来得到我需要的列:
cat <file.txt> | awk '{ print }'
这让我想到了这个:
NAME
xxxx0001
xxxx0002
xxxx0003
xxxx0004
xxxx0005
xxxx0006
xxxx0008
xxxx0008
但我不知道从这里去哪里。
我是否需要遍历列表项并进行解析以便仅获取数字,然后开始与下一行进行一些比较?
任何帮助将不胜感激
谢谢!
作为起点,请尝试以下操作:
awk '
NR>1 { gsub("[^0-9]", "", ); count[]++ }
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
用于跳过顶部 header 行。
gsub("[^0-9]", "", )
从 </code> 中删除了 non-number 个字符。
结果,<code>
被设置为从第 5 列中提取的数字。
- 数组
count[]
计算每个数字出现的次数。如果值
是 0
(或未定义),表示跳过该数字。如果值
大于1
,数字重复。
END { ... }
块被执行在所有输入行被处理之后
报告最终结果很有用。
但是,"Skipped/Duplicates" 方法无法很好地检测出以下情况:
# 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
最好在预期值和实际值之间进行line-by-line比较。那怎么样:
awk '
NR>1 {
gsub("[^0-9]", "", )
if ( != NR-1) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-1,
} ' file.txt
原始示例的输出:
Line: 8 Expected: xxxx0007 Actual: xxxx0008
[编辑]
根据包含更多额外 header 行的修改后的输入文件,如何:
awk '
f {
gsub("[^0-9]", "", )
if ( != NR-skip) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-skip,
}
/^#[[:blank:]]+LOCATION[[:blank:]]+TIME REFERENCE/ {
skip = NR
f = 1
}
' file.txt
输出:
Line: 19 Expected: xxxx0007 Actual: xxxx0008
上面的脚本会跳过这些行,直到找到特定的模式 # LOCATION TIME REFERENCE
。
- 如果
f
为真,则执行 f { ... }
块。所以该块被跳过
直到 f
设置为非零值。
- 如果输入行匹配则执行
/^# .../ { ... }
块
图案。如果找到,skip
设置为 header 行数,并且
f
(flag) 被设置为 1 所以上面的块从下一个开始执行
迭代。
希望这对您有所帮助。
在一个文本文件中,我在一列中有一个数字序列,前面有一个短字符串。这是此处示例文件中的第 5 列 "NAME":
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 重复。
因此,我希望能够检查数字是否为:
- sequential given the range that presently exists in the column.
- if there are any duplicates
我也想输出这些结果:
SKIPPED:
xxxx0007
DUPLICATES:
xxxx0008
我能得到的最远的是使用awk
来得到我需要的列:
cat <file.txt> | awk '{ print }'
这让我想到了这个:
NAME
xxxx0001
xxxx0002
xxxx0003
xxxx0004
xxxx0005
xxxx0006
xxxx0008
xxxx0008
但我不知道从这里去哪里。
我是否需要遍历列表项并进行解析以便仅获取数字,然后开始与下一行进行一些比较?
任何帮助将不胜感激 谢谢!
作为起点,请尝试以下操作:
awk '
NR>1 { gsub("[^0-9]", "", ); count[]++ }
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
用于跳过顶部 header 行。 gsub("[^0-9]", "", )
从</code> 中删除了 non-number 个字符。 结果,<code>
被设置为从第 5 列中提取的数字。- 数组
count[]
计算每个数字出现的次数。如果值 是0
(或未定义),表示跳过该数字。如果值 大于1
,数字重复。 END { ... }
块被执行在所有输入行被处理之后 报告最终结果很有用。
但是,"Skipped/Duplicates" 方法无法很好地检测出以下情况:
# 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
最好在预期值和实际值之间进行line-by-line比较。那怎么样:
awk '
NR>1 {
gsub("[^0-9]", "", )
if ( != NR-1) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-1,
} ' file.txt
原始示例的输出:
Line: 8 Expected: xxxx0007 Actual: xxxx0008
[编辑]
根据包含更多额外 header 行的修改后的输入文件,如何:
awk '
f {
gsub("[^0-9]", "", )
if ( != NR-skip) printf "Line: %d Expected: xxxx%04d Actual: xxxx%04d\n", NR, NR-skip,
}
/^#[[:blank:]]+LOCATION[[:blank:]]+TIME REFERENCE/ {
skip = NR
f = 1
}
' file.txt
输出:
Line: 19 Expected: xxxx0007 Actual: xxxx0008
上面的脚本会跳过这些行,直到找到特定的模式 # LOCATION TIME REFERENCE
。
- 如果
f
为真,则执行f { ... }
块。所以该块被跳过 直到f
设置为非零值。 - 如果输入行匹配则执行
/^# .../ { ... }
块 图案。如果找到,skip
设置为 header 行数,并且f
(flag) 被设置为 1 所以上面的块从下一个开始执行 迭代。
希望这对您有所帮助。