bash에서 명령 출력의 첫 번째 단어를 검색하는 방법은 무엇입니까?


127

예를 들어 다음과 같은 명령이 있습니다 echo "word1 word2". 파이프 ( |) 를 넣고 명령에서 word1을 얻고 싶습니다 .

echo "word1 word2" | ....

나는 파이프 뒤에 무엇을 넣어야할지 모르겠다.

답변:


201

Awk는 후행 공백을 처리해야하는 경우 좋은 옵션입니다.

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

하지만 컷은 이것을 처리하지 않습니다.

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

여기서 'cut'은 공백 / 공백을 인쇄하지 않습니다. 공백 앞에있는 첫 번째 항목은 다른 공백 이었기 때문입니다.


세미콜론이 필요합니까?
Alice Purcell

1
"후행"이 아니라 "선행"공백 (문자열 시작 부분)이어야합니다.
user202729

@AlicePurcell 나는없이 그것을 시도했다; 그것은 (MBP 10.14.2) 나를 위해 일한
새미 Bencherif

1
문자열이 공백으로 그 awk 명령 구분 문자로 예를 들어 "firstWord, secondWord"경우이 작동하지 않습니다
로저 오바

@RogerOba OP의 질문은 아니지만 -F","쉼표로 기본 필드 구분 기호 (공백)를 재정의하는 데 사용할 수 있습니다.
pjd

70

외부 명령을 사용할 필요가 없습니다. 배쉬 자체가 그 일을 할 수 있습니다. "word1 word2"를 어딘가에서 가져와 변수에 저장했다고 가정합니다. 예 :

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

이제 원하는 경우 $ 1 또는 $ 2 등을 다른 변수에 할당 할 수 있습니다.


11
셸 내장 및 stdin. M. @ 매트의 --수단은 stdin, 그래서 $string로 전달되고있다 stdin. stdin인수에 공백으로 분리 $1, $2, $3, 등 - 단지 배쉬 프로그램 평가하여 인수 (예를 들어 체크 할 때처럼 $1, $2등),이 방법은 분할 쉘의 경향을 활용 stdin에 대한 필요성을 제거, 자동 인수로 awk또는 cut.
Caleb Xu 2014

3
@CalebXu stdin이 아니라 set셸 인수를 설정합니다.
Guido

9
word1=$(IFS=" " ; set -- $string ; echo $1)단어 사이의 공백을 올바르게 인식하도록 IFS를 설정하십시오. $ 1의 원본 콘텐츠를 방해하지 않도록 괄호로 묶습니다.
Steve Pitchers

이것은 경로 이름 확장의 영향을 받기 때문에 깨졌습니다. 그것을보십시오 string="*". 놀라다.
gniourf_gniourf

32

효율적인 방법 중 하나는 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 Home

이것은 경로 이름 확장의 영향을 받기 때문에 깨졌습니다. 그것을보십시오 string="*". 놀라다.
gniourf_gniourf

while구문을 사용하여 각 줄에서 모든 첫 번째 단어를 검색합니다. 그렇지 않으면 Boontawee Home 접근 방식을 사용하십시오. 또한 echo "${array[0]}"gniourf-gniourf에서 알 수 있듯이 확장을 방지하기 위해 인용되었습니다.
Isaías

단어 수보다 큰 배열 인덱스에 액세스하려고하면 오류가 발생하지 않습니다. 빈 줄이 표시됩니다
Dhumil Agarwal

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

이것은 외부 명령을 사용하지 않고 $ 1, $ 2 등의 변수를 그대로 두는 장점이 있습니다.


변수를 $1, $2, …그대로 두는 것은 스크립트 작성에 매우 유용한 기능입니다!
Serge Stroobandt 2016 년

15

선행 공백이없는 것이 확실한 경우 bash 매개 변수 대체를 사용할 수 있습니다.

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

단일 공간을 벗어나지 않도록주의하십시오. 대체 패턴의 더 많은 예는 여기 를 참조 하십시오 . bash> 3.0 인 경우 정규식 일치를 사용하여 선행 공백에 대처할 수도 있습니다 . 여기를 참조 하십시오 .

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

11

당신은 awk을 시도 할 수 있습니다

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

awk를 사용하면 좋아하는 단어를 고르는 것이 정말 쉽습니다 ($ 1, $ 2, ...)


11

셸 매개 변수 확장 사용 %% *

다음은 쉘 매개 변수 확장을 사용하는 또 다른 솔루션 입니다. 첫 단어 뒤의 여러 공백을 처리합니다. 첫 번째 단어 앞의 공백을 처리하려면 추가 확장이 필요합니다.

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 ; }

나는 215 개의 5 글자 단어가 포함 된 테스트 문자열을 사용하여 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")

유권자 여러분, 잘하셨습니다 👏 투표는 솔루션의 속도와 일치합니다!


대시는 배열을 지원하지 않기 때문에 대시에서 3을 측정 할 수 있다는 것이 이상합니다 (대시에서는 read -a유효 하지 않음 ).
gniourf_gniourf

그래 이상해. 나는 그것을 배제하고 속도 테스트를 한 다음 "내가 왜 그것을 놔 두어야 할까"라고 생각하고 그것을 추가했습니다. 지금 제거하고 나중에 실수하지 않았는지 확인하기 위해 나중에 다시 실행할 수 있습니다
henry

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

cut은 문자열 ""(-d "")로 구분 된 필드 목록에서 첫 번째 필드 (-f 1)를 자릅니다.


그것은 한 가지 방법이지만, 그가 나중에 word2를 얻고 자한다면 당신의 cut 서술문은 단어들 사이의 여러 공백을 구별하지 않을 것입니다
ghostdog74

네, awk 솔루션이 더 좋습니다.
lajuette 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"; }

    두 번째 경우 : 각 줄의 첫 번째 단어가 필요합니다.

    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로 작업했습니다. 첫 번째 단어 앞에 여러 공백을 지원합니다 ( cutbash솔루션이 처리하지 않음).

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

psbash 만 사용하는 다른 솔루션은 ps정렬에 사용 되는 첫 번째 공백을 제거 할 수 없었기 때문에 프로세스 ID를 찾을 때 매우 유용했습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.