web-dev-qa-db-ja.com

grepを使用して文字の位置を見つける方法は?

Grepコマンドを使用して、文字列内の文字の位置を特定する必要があります。

たとえば、文字列はRAMSITALSKHMAN|1223333です。

grep -n '[^a-zA-Z0-9\$\~\%\#\^]'

指定した文字列で|の位置を見つけるにはどうすればよいですか?

10
user82782

-bを使用してバイトオフセットを取得できます。これは、単純なテキストの位置と同じです(ただし、UTF-8などの場合は異なります)。

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|

上記では、-aスイッチを使用して、入力をテキストとして使用するようにgrepに指示しています。バイナリファイルを操作するときに必要であり、-oスイッチは一致する文字のみを出力します。

位置だけが必要な場合は、grepを使用して位置のみを抽出できます。

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14

奇妙な出力が表示される場合は、grepで色が有効になっているかどうかを確認してください。 --colors=neverをgrepに渡すか、grepコマンドの前に\(エイリアスを無効にします)を付けることで、色を無効にできます。例:

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14

複数の一致を返す文字列の場合は、head -n1をパイプ処理して最初の一致を取得します。

上記の両方を使用していることに注意してください。後者は、実行可能ファイル(スクリプトなど)を介してgrepが「エイリアス」されている場合、エイリアスを使用する場合にのみ機能しません。

28
runejuhl

試してください:

printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'

出力:

15:|

これにより、index based-1の位置が得られます。

11
cuonglm

bash シェルを使用している場合、 grepawk などの外部プロセスを生成する必要なく、純粋に組み込みの操作を使用できます。 :

$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$ 

これは パラメータ展開 を使用して、|の後に出現するすべての文字列を削除し、一時変数に保存します。その場合、|のインデックスを取得するには、一時変数の長さを測定するだけです。

ifは、元の文字列に|が存在するかどうかを確認していることに注意してください。そうでない場合、一時変数は元の変数と同じになります。

また、これは|のゼロベースのインデックスを提供することに注意してください。これは、bash文字列にインデックスを付けるときに一般的に役立ちます。ただし、1から始まるインデックスが必要な場合は、次のようにすることができます。

$ echo $((${#tmp}+1))
15
$ 
8
Digital Trauma

Awkのindex関数を使用して、一致が発生した位置を文字で返すことができます。

echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15

Perlのindex関数を使用してもかまわない場合、これは文字の0回、1回以上の出現の報告を処理します。

echo "|abc|xyz|123456|zzz|" | \
Perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'

読みやすくするためにのみ、パイプラインは2行に分割されています。

ターゲット文字が見つかる限り、indexはゼロ(0)を基準とする正の値を返します。したがって、文字列 "abc | xyz | 123456 | zzz |"解析すると、位置0、4、8、15、19が返されます。

4
JRFerguson

「expr match」または「expr index」を使用してそれを行うこともできます

expr $ string $ substring match $ substringはREです。

echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`

そして、上記は一致した部分文字列の長さを返すため、位置を示します。

しかし、インデックスを検索するためにより具体的には:

mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
3
bluefoggy

別のawkコマンド

$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15

フィールド区切り文字をnull文字列として設定することにより、awkはレコード内の個々の文字を個別のフィールドとして扱います。

2
Avinash Raj

いくつかの選択肢は次のとおりです。

gnoucの答えに似ていますが、シェルを使用しています:

echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n | 
sh

sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'

seddcは複数行にわたる可能性があります:

echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc

15

$IFS...

IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))

多くのがどのようにあるかを教えてくれます...

echo $(($#-1))
2
mikeserv