Grepコマンドを使用して、文字列内の文字の位置を特定する必要があります。
たとえば、文字列はRAMSITALSKHMAN|1223333
です。
grep -n '[^a-zA-Z0-9\$\~\%\#\^]'
指定した文字列で|
の位置を見つけるにはどうすればよいですか?
-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が「エイリアス」されている場合、エイリアスを使用する場合にのみ機能しません。
試してください:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
出力:
15:|
これにより、index based-1の位置が得られます。
bash シェルを使用している場合、 grep や awk などの外部プロセスを生成する必要なく、純粋に組み込みの操作を使用できます。 :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
これは パラメータ展開 を使用して、|
の後に出現するすべての文字列を削除し、一時変数に保存します。その場合、|
のインデックスを取得するには、一時変数の長さを測定するだけです。
if
は、元の文字列に|
が存在するかどうかを確認していることに注意してください。そうでない場合、一時変数は元の変数と同じになります。
また、これは|
のゼロベースのインデックスを提供することに注意してください。これは、bash文字列にインデックスを付けるときに一般的に役立ちます。ただし、1から始まるインデックスが必要な場合は、次のようにすることができます。
$ echo $((${#tmp}+1))
15
$
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が返されます。
「expr match」または「expr index」を使用してそれを行うこともできます
expr $ string $ substring match $ substringはREです。
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
そして、上記は一致した部分文字列の長さを返すため、位置を示します。
しかし、インデックスを検索するためにより具体的には:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
フィールド区切り文字をnull文字列として設定することにより、awkはレコード内の個々の文字を個別のフィールドとして扱います。
いくつかの選択肢は次のとおりです。
gnoucの答えに似ていますが、シェルを使用しています:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
sed
とdc
は複数行にわたる可能性があります:
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))