ファイルから複数行のパターンを検索する方法を探しています。
たとえば、次の数値リストが入力ファイルであるとします。
3
2
5
4
8
2
5
4
2
4
2
5
4
2-4行(含む)のインスタンスを検索する場合、結果は次のようになります。
3
これは、特定の行が繰り返される正確な回数であるためです。また、ファイル内の特定の行数と行番号の特定の範囲を処理できるようにしたいです。
答え1
使用できるpcregrep、ほとんどのディストリビューションで利用可能です。次のコマンドは固定文字列と一致します。
pcregrep -Mc '^2\n5\n4$' input.txt
説明する
マニュアルページでは、pcregrepは「Perl互換正規表現を使用したgrep」です。
-M
:複数行の正規表現の一致-c
:一致自体ではなく一致数(count)を出力します。^2\n5\n4$
:それぞれ別々の行に2、5、4の正規表現。
代わりに、特定の線のパターン
質問の後続のコメントは、一致するパターンが固定文字列ではなく、一般的な「2行目から4行目」であることを示唆しています。ここでは、コマンド置換を使用して入力ファイルの行を解析できます。
pcregrep -Mc "^\Q$(sed -n 2,4p input.txt)\E$" input.txt
説明する
tail -n+2 input.txt
:出力ファイル、ライン2から始まるhead -n3
:最初の3行のみ出力\Q...\E
:引用する正規表現一致ではなく、デフォルトの文字列一致...
(コマンドの出力に対応する項目が含まれていないと仮定\E
)。
replacement( )sed ... input.txt
コマンドが削除されるため、出力の最後の数行は空ではないと仮定します。$(...)
みんな末尾の改行文字。
答え2
$ perl -l -0777pe '$_=()=/^2\n5\n4$/mg' input_file
3
布材:
-0777
=>フルルックサウンドモードは、ファイル全体を読むことを意味します。-p
=>次のレコードを読み取る前に、現在のレコードを標準出力に印刷します$_
。-l
=> RS設定= ORS = "\n"- 正規表現は私たちの場合、ファイル全体
/^2\n5\n4$/mg
に暗黙的に適用されます。$_
文字列の始まりと文字列の終わりに加えて、正規表現修飾子は行の終わり/m
と始まりも一致する必要があります。修飾子は/g
ファイル全体からすべての一致を取得します。$_
- リストコンテキストでこれを行い、それを空のリストに割り当てます。したがって、 $_ にはリスト内の要素の数、つまり正規表現が実際に一致する回数が再割り当てされます。
ファタイ
答え3
あなたの投稿には正規表現サポートの要件は記載されていないため、固定リテラルテキスト文字列を検索すると想定します。
これは今まで見た中で最も速いアルゴリズムではないかもしれませんが、十分な時間があればうまくいくでしょう。同じ最初の行で始まり、同じSHA256ハッシュを持つ複数のN行パターンがある場合、誤った結果をもたらす小さな欠陥があります。可能なすべてのNラインパターンには独自のSHA256ハッシュがあるとします。
大容量ファイル、特にパターンの最初の行が多く含まれるファイルの場合、非常に遅くなる可能性があります。
#!/usr/bin/env bash
# What's the name of the list file?
LIST=list
# What's the name of the pattern file?
PATTERN=pattern
# We'll figure out how many times the pattern lines appear (consecutively) in the list.
# Where's your SHA256 tool?
SHA256=/sbin/sha256
# what's the first line of pattern?
PATTERN_START="$(head -1 $PATTERN)"
# where in the list does that single line appear (what line numbers?)
START_LINES="$(grep -nx "$PATTERN_START" $LIST | sed -e 's/:.*//')"
# how many lines long is the pattern?
PAT_LEN="$(grep -c ^ < $PATTERN)"
echo Pattern is $PAT_LEN lines long, and might start at any of these lines:
echo $START_LINES
PAT_HASH="$($SHA256 < "$PATTERN")"
# So how many times does $PATTERN appear consecutively in $LIST?
PAT_COUNT=0
for LINE in $START_LINES
do
HASH="$(tail +$LINE $LIST | head -$PAT_LEN | $SHA256 -q)"
if [ "$HASH" = "$PAT_HASH" ]
then
echo match at line $LINE
PAT_COUNT=$(($PAT_COUNT+1))
fi
done
echo The pattern was found $PAT_COUNT times
出力:
$ cat list
3
2
5
4
8
2
5
4
2
4
2
5
4
$ cat pattern
2
5
4
$ . foo.sh
Pattern is 3 lines long, and might start at any of these lines:
2 6 9 11
match at line 2
match at line 6
match at line 11
The pattern was found 3 times
答え4
どうですか?
a="2 5 4"; tr '\n' ' ' < test | grep -o "[^0-9]$a[^0-9]" | wc -l
必要な区切り記号を使用してください。
22 5 44
次のような場合、一致を防ぐために正規表現が必要です。