Bash 通过命令行检查列中的数字是否连续
在文本文件中,我在一列中有一个数字序列,前面有一个短字符串。这是示例文件中“名称”下的第5列:Bash 通过命令行检查列中的数字是否连续,bash,awk,command-line,number-formatting,string-parsing,Bash,Awk,Command Line,Number Formatting,String Parsing,在文本文件中,我在一列中有一个数字序列,前面有一个短字符串。这是示例文件中“名称”下的第5列: 在上面的示例中,0007缺失,0008重复 因此,我希望能够检查这些数字是否为: 给定列中当前存在的范围 如果有重复的 我还想输出这些结果: SKIPPED: xxxx0007 DUPLICATES: xxxx0008 我能得到的最远的结果是使用awk获得我需要的列: cat | awk'{print$5}' 这让我想到: NAME xxxx0001 xxxx0002 xxxx0003 xxxx
在上面的示例中,0007缺失,0008重复 因此,我希望能够检查这些数字是否为:
SKIPPED:
xxxx0007
DUPLICATES:
xxxx0008
我能得到的最远的结果是使用awk
获得我需要的列:
cat | awk'{print$5}'
这让我想到:
NAME
xxxx0001
xxxx0002
xxxx0003
xxxx0004
xxxx0005
xxxx0006
xxxx0008
xxxx0008
但我不知道该从这里走到哪里
我是否需要循环遍历列表项并进行解析,以便只获取数字,然后开始与下一行进行比较
任何帮助都将不胜感激
谢谢大家! 作为起点,请尝试以下操作:
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
- 条件
用于跳过顶部标题行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
或
最好在预期值和实际值之间进行逐行比较。那么:
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
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: 8 Expected: xxxx0007 Actual: 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
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
输出:
Skipped:
xxxx0007
Duplicates:
xxxx0008
Line: 19 Expected: xxxx0007 Actual: xxxx0008
上面的脚本跳过这些行,直到找到特定的模式#位置时间参考
- 如果
为真,则执行f
块。因此,将跳过该块 直到f{…}
设置为非零值f
- 如果输入行与
图案如果找到,
设置为标题行数和skip
(标志)设置为1,以便从下一个开始执行上一个块 迭代李>f
希望这能有所帮助。您为什么尝试使用awk而不是更高级的语言(如perl、python、Java等)来实现这一点。我不太确定如何通过1(一)次遍历来实现这一点。即使在
awk
(我相信这是可能的),代码维护起来也会很复杂。@azbarcea我没有在perl、Python或任何其他语言中尝试过它们,因为我不太精通!我知道这在更高级别上更容易实现,但我决心在命令行上找到实现方法!!这同样有效!!但是,在下面的示例中,我如何处理顶部有多余行的情况呢?我已经根据情况更新了答案。你能测试一下吗?它适用于带有额外行的新文本模式!然而,我仍然希望只看到跳过或重复的数字,而不是整个列表。我的实际文本文件案例有200多行,因此我希望看到一个较短的列表。现在,您可能已经了解了如何报告跳过或重复的行(在我的初始答案中),以及如何处理额外的标题行(在我的上一个答案中)。通过组合这些片段,您可以编写您想要的版本。如果您仍然有问题,请发布1)您的代码,2)复制问题的最小输入行集,3)预期输出。然后我们可以帮你完成代码。祝你好运我在回答中加了一些解释。希望它能帮助您理解代码。