web-dev-qa-db-ja.com

シェルスクリプトで文字列の最初の2文字を抽出する方法は?

たとえば、次の場合:

USCAGoleta9311734.5021-120.1287855805

私はちょうど抽出したい:

US
100
Greg

おそらくbashシェルを使用している(そして、コメントに基づいているように見える)場合、最も効率的な方法は、パラメーター展開のサブストリングバリアントを使用することです。

pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US

これにより、shortlongの最初の2文字に設定されます。 longが2文字より短い場合、shortは同じです。

プロセス内でのオーバーヘッドは発生しないため、多くの場合(レポートごとに50,000回など)実行する場合、このシェル内の方法は通常より優れています。外部プログラムを使用するすべてのソリューションは、そのオーバーヘッドの影響を受けます。

最小の長さも確認したい場合は、次のようなものを手前に埋めることができます。

pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.

これにより、長さが2文字未満であれば、右側にピリオド(または、tmpstrを作成するときに使用する文字を変更するだけで何か他のもの)が埋め込まれます。これが必要かどうかは明らかではありませんが、完全を期すためにそれを入れると思いました。


そうは言っても、外部プログラムでこれを行う方法はいくつかあります(使用可能なbashがない場合など)。

short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')

最初の2つ(cuthead)は、1行の文字列では同じです。基本的にどちらも最初の2文字を返すだけです。 cutは各行の最初の2文字を提供し、headは入力全体の最初の2文字を提供するという点で異なります

3番目はawkサブストリング関数を使用して最初の2文字を抽出し、4番目はsedキャプチャグループを使用して(()および\1を使用して)最初の2文字をキャプチャします文字を入力し、行全体をそれらに置き換えます。これらは両方ともcutに似ています-入力の各行の最初の2文字を提供します。

入力が単一の行であることが確実な場合、それらはどれも重要ではありません。それらはすべて同じ効果があります。

158
paxdiablo

最も簡単な方法は

${string:position:length}

$length$stringから$positionサブストリングを抽出する場所。

これはbashビルトインなので、awkまたはsedは必要ありません。

44
ennuikiller

あなたはいくつかの良い答えを得て、私は自分で組み込みのBashに行きますが、sedawkと(almost)について尋ねたので、誰も解決策を提供しませんでしたそれらに基づいて、私はあなたにこれらを提供します:

echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'

そして

echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'

awkの1つはかなり明白なはずですが、ここにsedの1つの説明があります。

  • 「s /」を置換
  • 行「^」の先頭から始まり、任意の文字「。」が続く任意の文字「..」の2つのグループ「()」 0回以上「*」を繰り返します(一部の特殊文字をエスケープするにはバックスラッシュが必要です)
  • 「/」によって、最初の(この場合のみ)グループの内容(ここで、バックスラッシュは、一致する部分式を参照する特別なエスケープです)
  • 完了 "/"
31

bashにいる場合は、次のように言うことができます。

bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab

これはまさにあなたが必要なものかもしれません…

7

ただgrep:

echo 'abcdef' | grep -Po "^.."        # ab
7
Amir Mehler

かなり遅いですが、ここにあります

sed 's/.//3g'

または

awk NF=1 FPAT=..

または

Perl -pe '$_=unpack a2'
4
Steven Penny

colrm —ファイルから列を削除する

最初の2文字を残すには、3から始まる列を削除するだけです

cat file | colrm 3
4
Ian Yang

シェルスクリプトを使用し、非POSIX拡張機能(いわゆるbashismなど)に依存しない場合は、grep、sed、cut、awkなどの外部ツールをフォークする必要のない手法を使用できます。スクリプトの効率を下げます。ユースケースでは、効率とPOSIXの移植性は重要ではないかもしれません。ただし、それが(またはちょうど良い習慣として)ある場合は、次のparameter expansionオプションメソッドを使用して、シェルの最初の2文字を抽出できます。変数:

$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab

これは "smallest prefix"パラメータ展開を使用して最初の2文字(これは${var#??}部分)を削除し、次に「最小のサフィックス」パラメーターの展開${var%部分)。最初の2文字以外の文字列を元の値から削除します。

この方法は、これまでにこのセクションで説明されていました answer 「シェル=変数が#で始まるかどうかを確認する」質問に。この回答は、ここでの元の質問に適用されるものとは少し異なるコンテキストで使用できる、いくつかの同様のパラメーター展開方法についても説明しています。

1
Juan

printfを使用できます:

$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$orginal"
US
1
bschlueter

システムが別のシェル(bashではなく)を使用しているが、システムにbashがある場合、bashを呼び出すことで、bashの固有の文字列操作を使用できます。変数:

strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
1
palswim
Perl -ple 's/^(..).*/$1/'
0
dsm

これはあなたの後ですか?

my $string = 'USCAGoleta9311734.5021-120.1287855805';

my $first_two_chars = substr $string, 0, 2;

ref: substr

0
draegtun

mystring = USCAGoleta9311734.5021-120.1287855805の場合

print substr(mystring,0,2)

米国を印刷します

ここで、0は開始位置、2は読みにくい文字です。

0
Jambobond