bashでコマンドの出力の最初の単語を取得する方法は?


126

たとえば、コマンドがありますecho "word1 word2"。パイプ(|)を挿入して、コマンドからword1を取得します。

echo "word1 word2" | ....

パイプの後に何を置くかわかりません。

回答:


201

末尾の空白を処理する必要がある場合は、awkが適切なオプションです。

echo "   word1  word2 " | awk '{print $1;}' # Prints "word1"

ただし、Cutはこれを処理しません。

echo "  word1  word2 " | cut -f 1 -d " " # Prints nothing/whitespace

スペースの前の最初のものが別のスペースだったので、ここで 'cut'は何も/空白を出力しません。


セミコロンは必要ですか?
アリスパーセル

1
「先頭」の空白(文字列の先頭)であり、「末尾」ではありません。
user202729 2018年

@AlicePurcell私はそれなしでそれを試しました。そしてそれは私のために働いた(MBP 10.14.2)
Samy Bencherif '26

1
文字列が "firstWord、secondWord"の場合、これは機能しません。そのawkコマンドはスペースで区切られているためです
Roger Oba

@RogerObaそれはOPの質問ではありませんでした-F","が、デフォルトのフィールド区切り文字(スペース)をコンマで上書きするために使用できます。
pjd

70

外部コマンドを使用する必要はありません。バッシュ自体がその仕事をすることができます。「word1 word2」がどこかから取得され、変数に格納されていると仮定します。

$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2

これで、必要に応じて、$ 1や$ 2などを別の変数に割り当てることができます。


11
シェルビルトインとのみを使用する場合は+1 stdin。@Matt M. --はを意味するstdinため$string、として渡されstdinます。stdin引数に空白で分離され$1$2$3、など-ちょうどバッシュプログラム評価する引数(例えば、チェックするときのように$1$2など)は、このアプローチは分割するシェルの傾向を活用するstdinために必要がなくなり、自動的に引数にawkcut
Caleb Xu

3
@CalebXu stdinではなくset、シェル引数を設定します。
グイド

9
word1=$(IFS=" " ; set -- $string ; echo $1)単語間のスペースを正しく認識するようにIFSを設定します。元の$ 1の内容を壊さないように、括弧で囲みます。
スティーブピッチャー、

これはパス名の展開の影響を受けるため、壊れています。でお試しくださいstring="*"。驚き。
gniourf_gniourf 2018年

32

効率的な方法の1つは、bash配列を使用することです。

array=( $string ) # do not use quotes in order to allow word expansion
echo ${array[0]}  # You can retrieve any word. Index runs from 0 to length-1

また、パイプラインで配列を直接読み取ることもできます。

echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done

1
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
Boontaweeホーム

これはパス名の展開の影響を受けるため、壊れています。でお試しくださいstring="*"。驚き。
gniourf_gniourf 2018年

while構文を使用して、各行の最初の単語をすべて取得します。それ以外の場合は、Boontawee Homeアプローチを使用します。また、echo "${array[0]}"gniourf-gniourfによって通知されるように、拡張を防ぐために引用されていることに注意してください。
イザヤ

単語数より大きい配列のインデックスにアクセスしようとしても、エラーは発生しません。空の行が表示されます
Dhumil Agarwal

26
echo "word1 word2 word3" | { read first rest ; echo $first ; }

これには、外部コマンドを使用せず、$ 1、$ 2などの変数をそのまま残すという利点があります。


変数を$1, $2, …そのままにしておくことは、スクリプト作成に非常に役立つ機能です。
Serge Stroobandt

14

先行スペースがないことが確実な場合は、bashパラメータ置換を使用できます。

$ string="word1  word2"
$ echo ${string/%\ */}
word1

1つのスペースをエスケープすることに注意してください。置換パターンのその他の例については、こちらをご覧ください。bash> 3.0の場合、正規表現マッチングを使用して先行スペースに対処することもできます- ここを参照してください

$ string="  word1   word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1

11

あなたはawkを試すことができます

echo "word1 word2" | awk '{ print $1 }'

awkを使用すると、好きな単語を簡単に選択できます($ 1、$ 2、...)


11

シェルパラメータ展開の使用 %% *

これは、シェルパラメータ展開を使用した別のソリューションです。最初の単語の後の複数のスペースを処理します。最初の単語の前のスペースを処理するには、さらに1つの拡張が必要です。

string='word1    word2'
echo ${string%% *}
word1

string='word1    word2      '
echo ${string%% *}
word1

説明

%%が意味削除の最長の可能なマッチ *で(どの他の任意の数の文字に続く空間)末尾の一部string


9

速度の点で、上位の回答のいくつかがどのように評価されるのかと思いました。私は以下をテストしました:

1 @mattbh

echo "..." | awk '{print $1;}'

2 @ ghostdog74's

string="..."; set -- $string; echo $1

3 @ boontawee-home's

echo "..." | { read -a array ; echo ${array[0]} ; }

4 @ boontawee-home's

echo "..." | { read first _ ; echo $first ; }

5文字の単語が215のテスト文字列を使用して、macOSのZsh端末のBashスクリプトでPythonのtimeitを使用して測定しました。各測定を5回行って(結果はすべて100ループであり、3つのうち最良)、結果を平均しました。

method       time
--------------------------------
1. awk       9.2ms
2. set       11.6ms (1.26 * "1")
3. read -a   11.7ms (1.27 * "1")
4. read      13.6ms (1.48 * "1")

いい仕事、有権者👏投票(この記事の執筆時点で)はソリューションの速度と一致しています!


ダッシュは配列をサポートしていないため(read -aダッシュでは無効)、ダッシュで3を測定できるのは奇妙です。
gniourf_gniourf 2018年

変だね。私はそれを除外し、速度テストを行った後、「なぜそれを除外したのか」と考えて追加しました。今すぐ削除して、後で再実行して、間違いがないことを確認します
ヘンリー

6
echo "word1 word2" | cut -f 1 -d " "

cutは、文字列 ""(-d "")で区切られたフィールドのリストから最初のフィールド(-f 1)を切り取ります


一つの方法だが、彼は後にWORD2取得したい場合は、あなたのカットの文は単語の間に複数のスペースを区別しないこと
ghostdog74

はい、awkソリューションの方が優れています。
ラジュエット2014年

3

read あなたの友だちです:

  • 文字列が変数にある場合:

    string="word1 word2"
    read -r first _ <<< "$string"
    printf '%s\n' "$first"
  • パイプで作業している場合:最初のケース:最初の行の最初の単語のみが必要です。

    printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }

    2番目のケース:各行の最初の単語が必要です。

    printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done

これらは、先行スペースがある場合に機能します。

printf '%s\n' "   word1 word2" | { read -r first _; printf '%s\n' "$first"; }

0

perlにawkの機能が組み込まれているため、これはperlでも解決できます。

echo " word1 word2" | perl -lane 'print $F[0]'

0

私は、perl、awk、またはpythonを含まない組み込みデバイスを使用していて、代わりにsedを使用していました。最初の単語の前の複数のスペースをサポートします(これはcutおよびbashソリューションでは処理されませんでした)。

VARIABLE="  first_word_with_spaces_before_and_after  another_word  "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'

psここでbashのみを使用する他のソリューションでpsは、位置合わせに使用する最初のスペースを削除できなかったため、これはプロセスIDのgreppingに非常に役立ちました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.