Bash:変数のコンテンツで発生する最初の数値を取得する方法


8

変数の最初の数を取得する方法

変数があります:

STR="My horse weighs 3000 kg but the car weighs more"
STR="Maruska found 000011 mushrooms but only 001 was not with meat"
STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

私は数字を取得する必要があります:

3000
11
20

回答:


7

gawkでは、レコード区切り文字RSを一連の数字に設定します。RSパターンに一致したテキストは、を介して取得できますRT0to RTを追加して、それを強制的に数値にします(したがって、先行ゼロを削除します)。最初のインスタンスが出力されたらすぐに終了します

awk -v RS=[0-9]+ '{print RT+0;exit}' <<< "$STR"

またはここにbashソリューションがあります

shopt -s extglob
read -r Z _ <<< "${STR//[^[:digit:] ]/}"
echo ${Z##+(0)}

いいね。詳しく説明しますか?
jasonwryan 2013

わかりません。私は何を間違っていますか(awkバージョンで)?gist.github.com/jamiejackson/d92750cc42442a527c6b94499a13bc79
ジェイミージャクソン

@ JamieJackson、GNU awk(別名gawk)を実行していることを確認してください
iruvar

5

これを行う1つの方法を次に示します。

echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'

テスト:

$ STR="My horse weighs 3000 kg but the car weighs more"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
3000

$ STR="Maruska found 000011 mushrooms but only 001 was not with meat"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
11

$ STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
20

sed最後のの目的は何ですか?sedに入る前に、必要な結果が既に得られているようです。
マイケル

いいえ、あなたは#2の000011ために先行ゼロを削除する必要があります。しかし、あなたはマッチングによって簡素化することができ[1-9][0-9]*:スタートから先頭のゼロを削除します echo $STR | grep -o -E '[1-9][0-9]*'
CCH

2

の実装にgrepない場合、-oまたはBashを使用していない場合は、以下を実行できます。

printf "%.0f\n" $(printf "%s" "$string"|sed  's/^[^0-9]*//;s/[^0-9].*$//')

2
#!/bin/bash

string="My horse weighs 3000 kg but the car weighs more"

if [[ $string =~ ^([a-zA-Z\ ]*)([0-9]*)(.*)$ ]]
then
    echo ${BASH_REMATCH[1]}
fi  

1
下付き文字は1ではなく2にする必要がありますが、実際にはこのような正規表現の複合体は必要ありません。文字列に他の文字が含まれていると、とにかく失敗します。
追って通知があるまで一時停止。

2

このデモで簡単に反復できるように、文字列を配列に入れました。

これは、Bashの組み込みの正規表現マッチングを使用します。

非常に単純なパターンのみが必要です。一致テストに直接組み込むのではなく、変数を使用してパターンを保持することをお勧めします。より複雑なパターンには不可欠です。

str[0]="My horse weighs 3000 kg but the car weighs more"
str[1]="Maruska found 000011 mushrooms but only 001 was not with meat"
str[2]="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

patt='([[:digit:]]+)'

for s in "${str[@]}"; do [[ $s =~ $patt ]] && echo "[${BASH_REMATCH[1]}] - $s"; done

数字を視覚的に区別するためだけに角括弧を含めました。

出力:

[3000] - My horse weighs 3000 kg but the car weighs more
[000011] - Maruska found 000011 mushrooms but only 001 was not with meat
[0000020] - Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK

先頭のゼロなしで数値を取得するには、最も簡単な方法は、10を底とする変換を強制することです。

echo "$(( 10#${BASH_REMATCH[1]} ))"

代わりに、出力は要求したもののようになります。

3000
11
20

1

正規表現とを検索しman grepます。

echo $STR | grep -o [0-9]*

先行ゼロを削除するには、それを数値として扱います。

LIT=$(echo $STR | grep -o [0-9]*)
VAL=$(expr $LIT + 0)
echo $VAL

ソリューションが失敗し、変数に2つの数値またはゼロが埋め込まれた数値が含まれています。
cuonglm 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.