데이터를 stdout ( command1 -p=aaa -v=bbb -i=4
)으로 출력하는 명령이 있습니다. 출력 라인은 다음 값을 가질 수 있습니다.
rate (10%) - name: value - 10Kbps
그 ‘속도’를 저장하기 위해 출력을 grep하고 싶습니다 (파이프가 여기서 유용 할 것입니다). 마지막으로 두 번째 명령의 매개 변수 값이 되길 원합니다 (말하자 command2 -t=${rate}
).
내 편이 까다로워 보인다. 파이프, grep, sed 등을 사용하는 방법을 더 잘 알고 싶습니다.
나는 그와 같은 많은 조합을 시도했지만 이것에 대해 혼란스러워합니다.
$ command1 -p=aaa -v=bbb -i=4 | grep "rate" 2>&1 command2 -t="rate was "${rate}
답변
매우 다른 두 가지 유형의 입력을 혼동하고 있습니다.
- 표준 입력 (
stdin
) - 명령 줄 인수
이것들은 다르며 다른 목적에 유용합니다. 일부 명령은 두 가지 방식으로 입력을받을 수 있지만 일반적으로 다르게 사용합니다. 예를 들어 다음 wc
명령을 사용하십시오.
-
다음을 통해 입력 전달
stdin
:ls | wc -l
이것은 출력의 라인을 계산합니다
ls
-
명령 행 인수로 입력 전달 :
wc -l $(ls)
이것은 인쇄 된 파일 목록의 줄 을 계산합니다 .
ls
완전히 다른 것들.
질문에 대답하기 위해 첫 번째 명령의 출력에서 속도를 캡처 한 다음 두 번째 명령의 명령 줄 인수로 속도를 사용하는 것처럼 들립니다. 이를 수행하는 한 가지 방법이 있습니다.
rate=$(command1 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p')
command2 -t "rate was $rate"
의 설명 sed
:
s/pattern/replacement/
명령은 몇 가지 패턴을 대체하는 것입니다- 패턴은 다음을 의미합니다. 행은 “rate”(
^rate
) 로 시작하고 그 뒤에 두 문자 (..
)가오고 0 개 이상의 숫자가오고 뒤에%
, 그 뒤에 텍스트 (.*
) 가 있어야합니다. \1
대체에서는에서 캡처 된 첫 번째 표현식의 컨텐츠를 의미\(...\)
하므로이 경우%
부호 앞의 숫자- 명령 의
-n
플래그는sed
기본적으로 줄을 인쇄하지 않음을 의미합니다.p
의 마지막s///
명령은 여분이 있다면 광고를 출력하는 것을 의미한다. 즉, 명령은 일치하는 경우에만 무언가를 인쇄합니다.
답변
나는 이것을 사용하는 경향이있다 :
command1 | xargs -I{} command2 {}
command1
대체 (괄호)를 사용하여 xargs의 출력을로 전달하십시오 command2
. command1이 널 종료 문자열 에 대해 find
사용 -print0
하고 추가 해야하는 경우 발견 된 각 항목 을 호출 합니다.-0
xargs
xargs
command2
귀하의 경우 (및 @Janos에서 sed 라인을 사용) :
command1 -p=aaa -v=bbb -i=4 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p' | xargs -I{} command2 -t="rate was {}"
답변
command1
이 echo 문을 사용하여 출력을 시뮬레이트하려면 다음을 수행하십시오.
$ echo -e "Foo\nrate (10%) - name: value - 10Kbps\nBar"
$ alias command1='echo -e "Blah\nrate (10%) - name: value - 10Kbps\nBlag"'
빠른 테스트 :
$ command1
Blah
rate (10%) - name: value - 10Kbps
Blag
그게 다 좋으 니 파싱하자.
$ command1 | grep 'rate'
rate (10%) - name: value - 10Kbps
그래서 우리는 우리가 원하는 라인을 얻 command1
습니다 command2
.
$ alias command2='echo'
$ command2 -t="rate was "$(command1 | grep 'rate')
-t=rate was rate (10%) - name: value - 10Kbps
"rate was "$(command1 | grep 'rate')
자동으로 연결될 것으로 기대 합니다. 공백으로 인해 작동하지 않으면 대신 다음과 같이 입력을 전달할 수 있어야합니다.
$ alias command2='echo'
$ command2 -t=$(echo '"rate was ' $(command1 | grep 'rate') '"')
-t="rate was rate (10%) - name: value - 10Kbps "
답변
답변
첫 번째 작업은 해당 라인에서 요율을 추출하는 것입니다. GNU grep (포함되지 않은 Linux 또는 Cygwin)을 사용하면이 -o
옵션을 사용할 수 있습니다 . 원하는 부분은 숫자 만 포함하고 그 뒤에 %
부호 가있는 부분 입니다. %
자체 를 추출하지 않으려면 너비 가 0 인 lookahead assertion 과 같은 추가 트릭이 필요합니다 %
.
command1 -p=aaa -v=bbb -i=4 | grep -o -P '[0-9]+(?=%)'
또 다른 가능성은 sed를 사용하는 것입니다. sed에서 행의 일부를 추출하려면 s
전체 행과 일치하는 정규식 (로 시작 ^
하고로 끝나는)과 함께 명령을 사용하여 $
그룹으로 유지할 부분 ( \(…\)
)을 사용하십시오. 전체 줄을 유지할 그룹의 내용으로 바꿉니다. 일반적으로, -n
기본 인쇄를 끄고 p
추출 할 항목이있는 행을 인쇄 하도록 수정자를 배치 하는 옵션을 전달하십시오 (여기서는 단일 행이 있으므로 중요하지 않음). 참조 일치하는 패턴 후 라인의 부분 만 반환 하고 주변의 문자를 인쇄하지 않고 ‘나오지도’와 일치하는 정규식 추출 더 나오지 트릭을.
command1 -p=aaa -v=bbb -i=4 | sed 's/^.*rate(\([0-9]*\)%).*$/\1/'
sed보다 더 융통성이 있습니다. Awk는 작은 명령형 언어로 각 줄에 대한 명령을 실행합니다. 요율을 추출하는 방법은 여러 가지가 있습니다. 두 번째 필드 (기본적으로 공백은 공백으로 구분됨)를 선택하고 숫자가 아닌 모든 문자를 제거합니다.
command1 -p=aaa -v=bbb -i=4 | awk '{gsub(/[^0-9]+/, "", $2); print $2}'
이제 속도를 추출 했으므로 다음 단계는에 인수로 전달하는 것 command2
입니다. 이를위한 도구는 명령 susbtitution 입니다. 명령을 안에 넣는 경우 $(…)
(달러 괄호), 해당 출력이 명령 행으로 대체됩니다. 명령의 출력은 각 공백 블록에서 개별 단어로 분리되며 각 단어는 와일드 카드 패턴으로 처리됩니다. 이런 일이 일어나지 않기를 원한다면, 명령어 치환에 큰 따옴표를 넣으십시오 : "$(…)"
. 큰 따옴표를 사용하면 명령 출력이 단일 매개 변수로 직접 사용됩니다 (출력 끝의 줄 바꿈이 제거되는 유일한 변환입니다).
command2 -t "$(command1 -p=aaa -v=bbb -i=4 |
sed 's/^.*rate(\([0-9]*\)%).*$/\1/')"
답변
사용할 수 있으며 grep
PCRE-Perl 호환 정규 표현식입니다. 이를 통해 grepping 할 때 결과에 문자열 “rate”를 포함시키지 않고 rate 값과 일치하도록 lookbehind를 활용할 수 있습니다.
예
$ echo "rate (10%) - name: value - 10Kbps" | grep -oP '(?<=^rate \()\d+'
10
세부
위와 같이 grep
작동합니다 :
-o
찾고있는 것만 반환합니다\d+
.이 값은 괄호 안의 숫자입니다.-P
grep의 PCRE 기능을 활성화합니다(?<=^rate \()
“rate (“로 시작하는 문자열 만 반환합니다.
command2
“rate”의 가치를 얻으려면 다음 command1
과 같이 실행할 수 있습니다 .
$ rate=$(command 1 | grep -oP '(?<=^rate \()\d+'
그런 다음 두 번째 명령에는 단순히 해당 변수를 사용합니다.
$ command2 -t=${rate}
당신은 공상을 얻고 한 줄로 만들 수 있습니다.
$ command2 -t=$(command1 | grep -oP '(?<=^rate \()\d+')
이것은 $(..)
실행 블록 내에서 command1을 실행하고 결과를 가져 와서 command2의 -t=..
스위치 에 포함시킵니다 .
답변
나는 일반적으로`command`를 사용하여 출력을 다른 명령의 인수로 배치합니다. 예를 들어, freebsd에서 프로세스 foo가 소비 한 자원을 찾으려면 다음과 같습니다.
procstat -r `pgrep -x foo`
여기서 pgrep은 프로세스의 PID를 인수로 예상하는 procstat 명령에 전달되는 프로세스 foo의 PID를 추출하는 데 사용됩니다.