提取具有非连续字符串的两个连续行
Extract two consecutive lines that have non-consecutive strings
我有一个非常大的文本文件,有 2 列和超过 10 mio 行。
大多数行在第 2 列中都有一个数字,该数字是上一行的第 2 列的数字 +1。但是,几千行的行为有所不同(请参见下面的示例)。
输入文件:
A 1
A 2
A 3
A 10
A 11
A 12
A 40
A 41
我想提取第 2 列中不符合 +1 增量的两行。
所需的输出文件:
A 3
A 10
A 12
A 40
是否有(优先)允许这样做的 awk 命令?
我尝试了几个代码来比较连续两行的第 2 列,但不幸的是我直到现在都失败了(见下面的代码)。
awk 'FNR==1 {print; next} ==p2+1 {print p [=12=]; p=""; next} {p=[=12=] ORS; p2=}' input.txt > output.txt
感谢您的帮助。最好的,
假设:
- 列是 tab-delimited
- 第 1 列可能包含白色 space(这在 OP 提供的样本中没有显示,但也没有排除)
- 感兴趣的行必须在第 1 列中具有相同的值(即,如果第 1 列中的值不同,那么我们不会费心比较第 2 列中的值,而是继续下一个输入行)
- 如果连续3行符合条件,则第2/中间行只打印一次
设置:
$ cat input.txt
A 1
A 2
A 3 # match
A 10 # match
A 11
A 12 # match
A 23 # match
A 40 # match
A 41
X to Z 101
X to Z 102 # match
X to Z 104 # match
X to Z 105
注意: 注释仅在此处添加以突出显示符合搜索条件的行
一个awk
想法:
awk -F'\t' '
FNR==1 { prevline=[=11=] }
FNR>1 { if ( == prev1 && +0 != prev2+1) {
if (prevline) print prevline
print
prevline="" # make sure this line is not printed again if next line also meets criteria
}
else
prevline=[=11=]
}
{ prev1=; prev2= }
' input.txt
这会生成:
A 3
A 10
A 12
A 23
A 40
X to Z 102
X to Z 104
我喜欢 perl 用于需要算术的文本处理。
$ perl -ane 'print and next if $.<3; print $p and print if $F[3]!=$fp+1; $fp=$F[3]; $p=$_' input.txt
| COLUMN 1 | COLUMN 2 |
| -------- | -------- |
| A | 3 |
| A | 10 |
| A | 12 |
| A | 40 |
- 这是使用
-a
自动拆分为 @F
。
- 打印前两行:
print and next if $.<3
- 在后续行中,如果第 4 个字段不正好比前面的第 4 个字段多一个,则打印前一行和当前行:
print $p and print if $F[3]!=$fp+1
- 将第 4 个字段保存为
$fp
,将整行保存为 $p
: $fp=$F[3]; $p=$_
请您尝试以下操作:
awk 'NR>1 {if (!=p2+1) print p ORS [=10=]} {p=[=10=]; p2=}' input.txt > output.txt
输出:
A 3
A 10
A 12
A 40
- 变量名称与您的相似:
p
保留上一行和
p2
保存上一行的第二列。
- 条件
NR>1
禁止在第一行打印。
if (!=p2+1) print p ORS [=15=]
打印成对的两行
满足条件
- 块
{p=[=16=]; p2=}
为下一次迭代保留当前行的值。
这可能适合您 (GNU sed):
sed -nE 'N;h
s/.*\s+(.*)\n.*(\s.*)/echo "$((+1))"/e;/^(.*)\s$/!{x;p;x};x;D' file
在整个文件中打开两行 window。
复制 window 并将第一行的第二列增加一。如果此修改后的值等于第二行的第二列,则打印这两行。
删除第一行并重复。
N.B。如果下一行满足相同的条件,这可能会将这些行中的第二行打印两次。
我有一个非常大的文本文件,有 2 列和超过 10 mio 行。 大多数行在第 2 列中都有一个数字,该数字是上一行的第 2 列的数字 +1。但是,几千行的行为有所不同(请参见下面的示例)。
输入文件:
A 1
A 2
A 3
A 10
A 11
A 12
A 40
A 41
我想提取第 2 列中不符合 +1 增量的两行。
所需的输出文件:
A 3
A 10
A 12
A 40
是否有(优先)允许这样做的 awk 命令? 我尝试了几个代码来比较连续两行的第 2 列,但不幸的是我直到现在都失败了(见下面的代码)。
awk 'FNR==1 {print; next} ==p2+1 {print p [=12=]; p=""; next} {p=[=12=] ORS; p2=}' input.txt > output.txt
感谢您的帮助。最好的,
假设:
- 列是 tab-delimited
- 第 1 列可能包含白色 space(这在 OP 提供的样本中没有显示,但也没有排除)
- 感兴趣的行必须在第 1 列中具有相同的值(即,如果第 1 列中的值不同,那么我们不会费心比较第 2 列中的值,而是继续下一个输入行)
- 如果连续3行符合条件,则第2/中间行只打印一次
设置:
$ cat input.txt
A 1
A 2
A 3 # match
A 10 # match
A 11
A 12 # match
A 23 # match
A 40 # match
A 41
X to Z 101
X to Z 102 # match
X to Z 104 # match
X to Z 105
注意: 注释仅在此处添加以突出显示符合搜索条件的行
一个awk
想法:
awk -F'\t' '
FNR==1 { prevline=[=11=] }
FNR>1 { if ( == prev1 && +0 != prev2+1) {
if (prevline) print prevline
print
prevline="" # make sure this line is not printed again if next line also meets criteria
}
else
prevline=[=11=]
}
{ prev1=; prev2= }
' input.txt
这会生成:
A 3
A 10
A 12
A 23
A 40
X to Z 102
X to Z 104
我喜欢 perl 用于需要算术的文本处理。
$ perl -ane 'print and next if $.<3; print $p and print if $F[3]!=$fp+1; $fp=$F[3]; $p=$_' input.txt
| COLUMN 1 | COLUMN 2 |
| -------- | -------- |
| A | 3 |
| A | 10 |
| A | 12 |
| A | 40 |
- 这是使用
-a
自动拆分为@F
。 - 打印前两行:
print and next if $.<3
- 在后续行中,如果第 4 个字段不正好比前面的第 4 个字段多一个,则打印前一行和当前行:
print $p and print if $F[3]!=$fp+1
- 将第 4 个字段保存为
$fp
,将整行保存为$p
:$fp=$F[3]; $p=$_
请您尝试以下操作:
awk 'NR>1 {if (!=p2+1) print p ORS [=10=]} {p=[=10=]; p2=}' input.txt > output.txt
输出:
A 3
A 10
A 12
A 40
- 变量名称与您的相似:
p
保留上一行和p2
保存上一行的第二列。 - 条件
NR>1
禁止在第一行打印。 if (!=p2+1) print p ORS [=15=]
打印成对的两行 满足条件- 块
{p=[=16=]; p2=}
为下一次迭代保留当前行的值。
这可能适合您 (GNU sed):
sed -nE 'N;h
s/.*\s+(.*)\n.*(\s.*)/echo "$((+1))"/e;/^(.*)\s$/!{x;p;x};x;D' file
在整个文件中打开两行 window。
复制 window 并将第一行的第二列增加一。如果此修改后的值等于第二行的第二列,则打印这两行。
删除第一行并重复。
N.B。如果下一行满足相同的条件,这可能会将这些行中的第二行打印两次。