数字でいっぱいのファイルがあり、各行には数字があります。各数字は2桁または3桁の数字で構成されています。
複数の連続した数字を含むランダムな数字でファイルをフィルタリングしたいと思います。これらの連続した数字は連続的(例えば127、215、781)、または不連続的(例えば506)であり得る。連続した数字の順序は重要ではありません。サイズは、小さいものから大きいもの(例えば127)、または大きいものから小さいもの(例えば215)であり得る。
たとえば、
127
215
781
874
370
01
10
142
506
94
予想出力:
370
94
なぜなら:
127 # Has two sequential and consecutive digits (1 and 2)
215 # Has two sequential and consecutive digits (1 and 2)
781 # Has two sequential and consecutive digits (7 and 8)
874 # Has two sequential and consecutive digits (7 and 8)
370 # Keep
01 # Has two sequential and consecutive digits (0 and 1)
10 # Has two sequential and consecutive digits (0 and 1)
142 # Has two sequential and non-consecutive digits (1 and 2)
506 # Has two sequential and non-consecutive digits (5 and 6)
94 # Keep
答え1
FSを空の文字列に設定しますawk
。空のFSを使用する効果はPOSIX固有の未定義の動作であり、awk
使用しているバージョンによって異なる結果が生じる可能性があります。以下はGNUでテストされましたawk
。
awk -F '' '{
is_sequential=0;
for (i=2; i<=NF; i++)
is_sequential+=($0 ~ $i-1 || $0 ~ $i+1)
}!is_sequential' infile
行全体のすべての数字が数字-1または数字+ 1と等しいことを確認してください$i
。つまり、行に 1 つの数字または 2 つの数字が表示されている場合は、隣に少なくとも 2 つの数字が見つかりました (セクション 1)。 、数値自体、および次または両方(順次)、したがって値$i-1
$i+1
number-1
number+1
$i
$i-1
$i+1
順次変数は増加し、そうでなければゼロのままです。
を使用して!is_sequential
値が変更されていない行を印刷します(値はまだあり、少なくとも0
2つの連続した数字は表示されません)。awkスクリプトの最後にある「1」とはどういう意味ですか?
または awk を使用してください。
awk '{
is_sequential=0;
for (i=1; i<=length(); i++) {
num=substr($0, i, 1)
is_sequential+=($0 ~ num-1 || $0 ~ num+1)
}
}!is_sequential' infile
答え2
試してみることができます
awk '
{split ("", N) # delete array N
L = 1 # initialise boolean L to TRUE
for (i=1; i<=length($1); i++){ # for each digit
P = substr($1, i, 1)
if (N[P-1] || N[P+1]){ # if contiguous digit exists,
L = 0
break # set L to FALSE; and quit the for loop
}
N[P] = 1
}
}
L
' file
出力:
370
94
または
awk '
{split ("", N)
L = 1
for (i=1; i<=length; i++)
N[substr($0,i,1)] = 1 # set all N elements for the digits in string
for (i=0; i<9; i++)
if (N[i] + N[i+1] == 2) { # check for two adjacent elements to be TRUE
L = 0
break
}
}
L
' file
出力:
370
94
Ubuntu 18.04でテストされました。
答え3
ここでは、組み合わせリストが比較的小さいので、ERE置換でこれを考慮することもできます。
grep -vE '0.*1|1.*[02]|2.*[13]|3.*[24]|4.*[35]|5.*[46]|6.*[57]|7.*[68]|8.*[79]|9.*8'
これと同じperl
ですが、正規表現内でPerlコードを使用して、(??{...})
次または前の数字と一致させます。
perl -ne 'print unless /([0-8]).*(??{$1+1})/ || /([1-9]).*(??{$1-1})/'
sedを使用すると、パターン空間に連続ペアのリストを追加し、逆参照を使用して一致するものを見つけることができます。
sed -ne '1{x;s/$/0123456789876543210/;x;}' -e 'G;/\(.\).*\(.\).*\n.*\1\2/!P'