[linux] Bash를 사용하여 열별로 명령 출력을 분할 하시겠습니까?

나는 이것을하고 싶다 :

  1. 명령을 실행하다
  2. 출력 캡처
  3. 라인을 선택
  4. 해당 행의 열을 선택

예를 들어, a에서 명령 이름을 얻고 싶다고 가정 해 봅시다 $PID(이것은 단지 예일뿐입니다. 이것이 프로세스 ID에서 명령 이름을 얻는 가장 쉬운 방법이라고 제안하는 것이 아닙니다. 실제 문제는 출력 형식을 제어 할 수없는 다른 명령).

내가 실행 ps하면 다음을 얻습니다.


  PID TTY          TIME CMD
11383 pts/1    00:00:00 bash
11771 pts/1    00:00:00 ps

지금은 어떻게 ps | egrep 11383얻을

11383 pts/1    00:00:00 bash

다음 단계 : ps | egrep 11383 | cut -d" " -f 4. 출력은 다음과 같습니다.

<absolutely nothing/>

문제는 cut단일 공백으로 출력 을 자르고 ps두 번째 열과 세 번째 열 사이에 공백 을 추가하여 테이블의 유사성을 유지 cut하면서 빈 문자열을 선택한다는 것입니다. 물론 cut4 번째 필드가 아닌 7 번째 필드를 선택하는 데 사용할 수 있지만, 특히 출력이 가변적이고 미리 알 수없는 경우 어떻게 알 수 있습니까?



답변

한 가지 쉬운 방법은 tr반복되는 필드 구분 기호를 짜내 는 패스를 추가하는 것입니다.

$ ps | egrep 11383 | tr -s ' ' | cut -d ' ' -f 4


답변

가장 간단한 방법은 awk 를 사용하는 것 입니다. 예:

$ echo "11383 pts/1    00:00:00 bash" | awk '{ print $4; }'
bash


답변

tr -s ' '옵션은 단일 선행 공백을 제거하지 않습니다. 열이 오른쪽 정렬 된 경우 ( pspid 와 같이 ) …

$ ps h -o pid,user -C ssh,sshd | tr -s " "
 1543 root
19645 root
19731 root

그런 다음 절단하면 해당 필드 중 일부가 첫 번째 열인 경우 빈 줄이 생깁니다.

$ <previous command> | cut -d ' ' -f1

19645
19731

앞에 공백이 없으면 분명히

$ <command> | sed -e "s/.*/ &/" | tr -s " "

이제 이름이 아닌 pid 숫자의이 특별한 경우에 다음과 같은 함수가 있습니다 pgrep.

$ pgrep ssh

쉘 기능

그러나 일반적 으로 명령 에 대한 깔끔한 점이 있기 때문에 실제로는 간결한 방식으로 쉘 함수 를 사용할 수 있습니다 read.

$ <command> | while read a b; do echo $a; done

읽을 첫 번째 매개 변수 a는 첫 번째 열을 선택하고 더 많은 항목 이있는 경우 다른 모든 항목 이에 입력됩니다 b. 결과적으로 +1 열의 수보다 더 많은 변수가 필요하지 않습니다. .

그래서,

while read a b c d; do echo $c; done

그런 다음 세 번째 열을 출력합니다. 내 의견에 표시된대로 …

파이프 된 읽기는 호출 스크립트에 변수를 전달하지 않는 환경에서 실행됩니다.

out=$(ps whatever | { read a b c d; echo $c; })

arr=($(ps whatever | { read a b c d; echo $c $b; }))
echo ${arr[1]}     # will output 'b'`

어레이 솔루션

그래서 우리는 @frayser의 대답으로 끝납니다. 이것은 기본적으로 공백을 사용하는 쉘 변수 IFS를 사용하여 문자열을 배열로 분할하는 것입니다. 그래도 Bash에서만 작동합니다. Dash와 Ash는이를 지원하지 않습니다. Busybox의 구성 요소로 문자열을 분할하는 데 정말 어려움을 겪었습니다. 단일 구성 요소 (예 : awk 사용)를 얻은 다음 필요한 모든 매개 변수에 대해이를 반복하는 것은 쉽습니다. 그러나 그런 다음 동일한 라인에서 반복적으로 awk를 호출하거나 동일한 라인에서 echo가있는 읽기 블록을 반복적으로 사용합니다. 효율적이거나 예쁘지 않습니다. 그래서 당신은 ${name%% *}등등. 익숙한 기능의 절반 이상이 사라지면 실제로 쉘 스크립팅이 더 이상 재미 있지 않기 때문에 일부 Python 기술을 갈망하게 만듭니다. 그러나 파이썬조차도 그러한 시스템에 설치되지 않을 것이며 ;-)가 아니라고 가정 할 수 있습니다.


답변

시험

ps |&
while read -p first second third fourth etc ; do
   if [[ $first == '11383' ]]
   then
       echo got: $fourth
   fi
done


답변

배열 변수 사용

set $(ps | egrep "^11383 "); echo $4

또는

A=( $(ps | egrep "^11383 ") ) ; echo ${A[3]}


답변

brianegge의 awk 솔루션과 유사하게 다음은 Perl에 해당하는 것입니다.

ps | egrep 11383 | perl -lane 'print $F[3]'

-a@F열 데이터로 배열 을 채우는 자동 분할 모드를 활성화 합니다. 데이터가 공백으로 구분되지 않고 쉼표로 구분 된 경우
사용 -F,합니다.

Perl이 1이 아닌 0부터 계산을 시작하므로 필드 3이 인쇄됩니다.


답변

올바른 줄 (6 번 줄의 예)을 얻는 것은 head와 tail로 이루어지며 올바른 단어 (단어 4 번)는 awk로 캡처 할 수 있습니다.

command|head -n 6|tail -n 1|awk '{print $4}'