
だから私は多くの情報を含むファイルを持っており、情報の各「塊」には次の一意の識別子があります。
「インデックス」:数字
Linuxで次のコマンドを使用した後:
$ cat file | grep index
私は次のような結果を得ます。
"index": 1
"index": 2
"index": 3
...
"index": 10001
その間に、連続形式の一連の数字があります。
そこのどこかに数字が抜けていますが、その数字を把握しようとしています。
私はいくつか試してみましたが、そのうち何も動作しませんでした。追加できる他のコマンドはありますか?または、欠落しているインデックスマークを検索するより良い方法はありますか?
答え1
このコマンドを使用して、diff
ファイルと N から M までの一連の数字の違いを確認できます。このawk
コマンドは、テキストを解析して数字のみを取得するために使用されます。
diff --side-by-side --suppress-common-lines <(awk '{print $2}' file.txt) <(seq 1 10001) | awk '{print $2}'
上記のコードは1
ファイル番号をのシーケンスと比較します10001
。
以上機能のこれを実装する方法は、ファイルの最後の番号(10001)を検出して変数に割り当てることです。
max=$(tail -1 file.txt | awk '{print $2}')
diff --side-by-side --suppress-common-lines <(awk '{print $2}' file.txt) <(seq 1 $max) | awk '{print $2}'
たとえば、次のようになります。
ファイル.txt:
"index": 1
"index": 5
"index": 8
"index": 9
"index": 10
"index": 12
"index": 13
"index": 15
max=$(tail -1 file.txt | awk '{print $2}')
diff --side-by-side --suppress-common-lines <(awk '{print $2}' file.txt) <(seq 1 $max) | awk '{print $2}'
出力:
2
3
4
6
7
11
14
ただし、欠落している値をこの形式で印刷するには、最後のステートメントを次のように"index": the_missing_number
変更できます。awk print
diff --side-by-side --suppress-common-lines <(awk '{print $2}' file.txt) <(seq 1 $max) | awk '{print "\"index\": "$2}'
答え2
あなたの例では、インデックスラベルと整数を含むファイルの2つの重要な仮定は次のとおりです。
"index": 1
"index": 2
"index": 3
...
"index": 10001
仮定は次のとおりです。
- 最初の行から最後の行まで読み取ると、インデックス整数は昇順にソートされます。
- 1 つ以上のスペースまたはタブは、
"index":
ラベルをインデックス整数と区別します。
この小さなループは両方とも真であるbash
欠けている数字を出力するかもしれません(しかし、コードの後ろの警告を読んでください)。インデックスラベルと整数を含むファイルの名前は次のとおりですindexes.txt
。
cur_idx=0
last_idx=0
while read label cur_idx; do
(( last_idx != ( cur_idx - 1 ))) && echo $(( cur_idx - 1 ))
last_idx=${cur_idx}
done < indexes.txt
ループは、表示された最後のインデックスを記憶し、新しいインデックス行を読み取り、現在の(新しい)インデックス[マイナス1]を最後のインデックスと比較します。同じでない場合は、インデックスをスキップしてスキップしたインデックスを印刷します。
警告する:
複数の連続した欠落インデックスがある場合、このループは最初の欠落インデックスのみを印刷します。すべての内容が印刷されるわけではありません。
つまり、次のような場合です。
"index": 21
"index": 24
(22
sum欠落23
)ループはを印刷します22
。ただし、これにより、indexes.txt
後でファイルを表示して21
スキップされた番号の数を確認できます。あなたの質問で私が受けた印象は、欠けているインデックスが1つまたは2つだけであるため、これがあなたを邪魔してはいけないということです。
答え3
単純なgrep / awkステートメントを使用してこれを実行できます。 awk行番号(NR)と同じ番号を持たない最初の行のインデックスを一致させ、行番号を印刷して終了します。
grep index file | awk -F: '{ if (NR != $2 ) {print "missing " NR; exit;} }'
答え4
使用幸せ(以前のPerl_6)
~$ raku -e 'my @a; for lines() {@a.push: $/.Int if .match(/<?after \"index\"\: \s > \d+ /) }; \
put ((1..10) (-) @a.Set).keys.sort;' index.txt
#OR
~$ raku -e 'my @a; for lines() {@a.push: $0.Int if .match(/<?after \"index\"\: \s > (\d+) /) }; \
put ((1..10) (-) @a.Set).keys.sort;' index.txt
RakuはPerlファミリーのプログラミング言語です。 2015年にPerl_6としてリリースされ、2019年にRakuに名前が変更されました。したがって、Rakuでは「Perl主義」をたくさん見つけることができます。
Rakuの興味深い機能の1つは集合セマンティクスです。 Unicode演算子とASCII演算子の両方を使用できます。上記のコードでは、(-)
ASCII差設定(非対称)。 Unicodeを使用することもできます。
∖
SET MINUS
Unicode: U+2216, UTF-8: E2 88 96
入力例(最大値は100):
"index": 1
"index": 2
"index": 3
"index": 5
"index": 100
サンプル出力(2つのコード例):
4 6 7 8 9 10
警告:対称と非対称のセット操作を混同しやすいです。たとえば、上記のコードの場合、コレクションの順序を逆にして ASCII(^)
や Unicode を試してみると⊖
対称セットの違い代わりに大きな違いがあります(1..99
テスト範囲として使用されます)。
~$ cat index.txt | perl6 -e 'my @a = do for lines() {$/.Int if .match(/<?after \"index\"\: \s > \d+ /) }; put (@a.Set (-) (1..99)).keys.sort;'
100
~$ cat index.txt | perl6 -e 'my @a = do for lines() {$/.Int if .match(/<?after \"index\"\: \s > \d+ /) }; put (@a.Set (^) (1..99)).keys.sort;'
4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100