bash : n 번째 출력 열을 얻는 가장 짧은 방법


165

작업 중에 bash의 일부 명령에서 다음과 같은 열 형식의 출력이 반복적으로 발생한다고 가정합니다 (제 경우에는 svn stRails 작업 디렉토리 에서 실행 ).

?       changes.patch
M       app/models/superman.rb
A       app/models/superwoman.rb

명령 출력 (이 경우 파일 이름)으로 작업하려면 두 번째 열을 다음 명령의 입력으로 사용할 수 있도록 일종의 구문 분석이 필요합니다.

내가하고있는 일은 awk두 번째 열을 얻는 데 사용하는 것입니다 . 예를 들어 모든 파일을 제거하려는 경우 (일반적인 유스 케이스는 아닙니다) :

svn st | awk '{print $2}' | xargs rm

내가 이것을 많이 입력했기 때문에 자연스러운 질문은 : bash에서 이것을 달성하는 더 짧은 (따뜻한) 방법이 있습니까?

참고 : 구체적인 질문은 svn 워크 플로에 있지만 본질적으로 쉘 명령 질문입니다. 워크 플로우가 어리 석고 대안 적 접근 방식을 제안한다고 생각한다면 투표하지 않을 것입니다. 그러나 여기서 가장 중요한 방법은 bash에서 n 번째 열 명령 출력을 가장 짧은 방법으로 얻는 방법입니다. . 감사 :)


1
명령을 자주 사용하면 스크립트를 작성하여 경로에 넣는 것이 좋습니다. 원하는 경우 bashrc에 간단히 함수를 만들 수 있습니다. 열 선택 표현식을 줄이는 지점이 보이지 않습니다.
Lynch

1
당신 말이 맞아요. '포인트'는 학습을 목적으로하지만 대부분 재미를 위해 배쉬에서 일을하는 새로운 방법에 대한 탐구입니다 :)
Sv1

1
또한 어딘가에 ssh-ing 할 때 .bashrc가 없으므로 경로가 없어도 길을 아는 것이 유용합니다.
Kos

답변:


125

cut두 번째 필드에 액세스하는 데 사용할 수 있습니다 .

cut -f2

편집 : 죄송합니다. SVN이 출력에 탭을 사용하지 않는다는 것을 몰랐으므로 약간 쓸모가 없습니다. cut출력에 맞출 수는 있지만 약간 깨지기 쉽습니다. cut -c 10- 작동하는 것과 같지만 정확한 값은 설정에 따라 다릅니다.

다른 옵션은 다음과 같습니다. sed 's/.\s\+//'


1
출력 cut -f2과 함께 사용하십시오 svn st. 당신은 그것이 작동하지 않는 것을 볼 수 있습니다.
Lynch

실제 svn st는 출력에 탭을 사용 한다고 가정했습니다 . 일부 테스트 후에는 그렇지 않습니다. 제길.
porges

21
-d이 작업을 수행 할 수 있도록 적절한 구분자를 전달하십시오 .
Yogh

6
@Yogh가 말한 것을 확장하면 공백으로 구분 기호는 다음과 같습니다 cut -d" " -f2.
adamyonk

표준 사용 xargs에 awk가 없음 : svn st | xargs | cut -d ""-f2
vr286

106

다음과 같은 것을 달성하십시오.

svn st | awk '{print $2}' | xargs rm

bash 만 사용하면 다음을 사용할 수 있습니다.

svn st | while read a b; do rm "$b"; done

물론 짧지는 않지만 조금 더 효율적이며 파일 이름의 공백을 올바르게 처리합니다.


무엇 ab어떻게 그들을 얻을?
Timo

1
@Timo a는 첫 번째 열을 b나타내고 나머지 열을 나타냅니다. 두 번째 열을 인쇄 read a b c;하려면을 echo대신 사용하십시오 rm. 나는 grep 패턴을 따르는 많은 ID 프로세스를 얻기 위해 이것을 사용하여 모든 것을 중단시킬 수있었습니다.
Matt Kleinsmith

36

나는 같은 상황에 처해 있었고이 별칭을 .profile파일에 추가했습니다 .

alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"

다음과 같이 쓸 수 있습니다.

svn st | c2 | xargs rm

15
배쉬 함수가 일반적으로 더 유용합니다. 나는 이것을했다 : function c() { awk "{print \$$1}" } 그러면 당신은 할 수있다 : svn st | c 2 | xargs rm
Aissen

8
그러나 여분의 공간을 입력해야합니다. 너무 피곤합니다 :)
StackedCrooked 2018 년

16

zsh를 사용해보십시오. 접미사 별명을 지원하므로 .zshrc에서 X를 다음과 같이 정의 할 수 있습니다.

alias -g X="| cut -d' ' -f2"

그럼 당신은 할 수 있습니다 :

cat file X

한 단계 더 나아가서 n 번째 열에 대해 정의 할 수 있습니다.

alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"

파일 "file"의 n 번째 열을 출력합니다. grep 출력 또는 더 적은 출력에도이 작업을 수행 할 수 있습니다. 이것은 매우 편리하고 zsh의 킬러 기능입니다.

한 단계 더 나아가서 D를 다음과 같이 정의 할 수 있습니다.

alias -g D="|xargs rm"

이제 다음을 입력 할 수 있습니다 :

cat file X1 D

파일 "file"의 첫 번째 열에 언급 된 모든 파일을 삭제합니다.

bash를 알고 있다면 zsh는 새로운 기능을 제외하고는 크게 변경되지 않습니다.

크리스 HTH


ahh, 위에 의견을 입력하는 동안 답변을 업데이트 한 것을 알 수 있습니다.) 어떤 열을 가져올 지 동적으로 지정할 수 있습니까? 또는 .zshrc에 n 줄이 필요합니까 (중요하지는 않지만 중요합니다)
Sv1

게시물을 추가로 수정하고 파일을 삭제하기 위해 접미사 "D"를 정의했습니다. 내가 아는 한 각 접미사에 줄을 추가해야합니다.
Chris

또는 X 명령의 첫 번째 매개 변수로 사용하십시오. 파이프를 별칭에 넣는 독특한 아이디어를 제외하고는 zsh 또는 별칭이 필요하지 않습니다.
tripleee

1
나는 왜 당신이 cut옵션 을 좋아하는지 이해하지 못합니다 . 의 출력을 사용하여 내 컴퓨터에서 작동하지 않습니다 svn st. svn st | cut -d' ' -f2무슨 일이 일어나는지 보십시오 .
Lynch

@ Sv1은 별칭이 명령이기 때문에 별칭을 정의하기위한 루프를 작성할 수 있습니다.
driftcatcher 2016

8

스크립트에 익숙하지 않은 것 같으므로 여기에 예가 있습니다.

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

이 저장이되면 ~/bin/x하고 있는지 확인 ~/bin당신에 PATH(지금은 당신이 당신에 넣어해야 할 뭔가 .bashrc당신이 일반적으로 열 N을 추출하기위한 가장 짧은 명령이는) x n.

숫자가 아닌 인수 또는 잘못된 수의 인수 등으로 호출 된 경우 스크립트는 적절한 오류 검사를 수행해야합니다. 이 베어 본 필수 버전을 확장하면 단위 102가됩니다.

다른 열 구분 기호를 허용하도록 스크립트를 확장하고 싶을 수도 있습니다. 기본적으로 Awk는 입력을 공백의 필드로 구문 분석합니다. 다른 분리 문자를 사용 하려면 새 분리 문자가있는 -F ':'위치를 사용 :하십시오. 이것을 스크립트의 옵션으로 구현하면 약간 길어 지므로 독자에게 연습으로 남겨 두겠습니다.


용법

주어진 파일 file:

1 2 3
4 5 6

stdin을 통해 전달할 수 있습니다 ( 무용cat 한 것을 더 유용한 것에 대한 자리 표시 자로 사용 ).

$ cat file | sh script.sh 2
2
5

또는 스크립트에 대한 인수로 제공하십시오.

$ sh script.sh 2 file
2
5

여기서는 sh script.sh스크립트가 script.sh현재 디렉토리와 같이 저장되었다고 가정합니다 . PATH위의 지침에서 와 같이 더 유용한 이름으로 저장하고 실행 파일로 표시하면 유용한 이름을 대신 사용하십시오 (및 no sh).


좋은 생각이지만 sh 또는 bash에있는 것처럼 나에게는 효과적이지 않습니다. #! / bin / bash col = $ 1 shift awk "{print \ $$ col}"
mgk

이 늦은 의견에 감사드립니다. 수정 사항으로 업데이트되었습니다.
tripleee

1
더 나은awk -v col=$col ...
fedorqui 'SO 중지 피해'12

@fedorqui 여기 및 다른 곳에서 의견을 보내 주셔서 감사합니다! 답변을 업데이트했습니다. 이제 약간 길어 졌으므로 가장 짧은 스크립트를 원한다면 원본 버전 의 개정 내역 을 참조하십시오 .
tripleee December

1
@fedorqui 감사합니다. cat히스테리 적 이유로 예제에 작은 경고를 추가했습니다 (-:
tripleee

5

이미 해결책이있는 것 같습니다. 일을 더 쉽게하기 위해 명령을 bash 스크립트 (짧은 이름으로)에 넣고 매번 'long'명령을 입력하는 대신 실행하는 것이 어떻습니까?


내 의견으로는 '멋지다'는 것이 아닙니다. 왜? 글쎄, 나는 .bashrc를 여러 가지 지름길로 넘치게하고 싶지 않고 본질적으로 메타 쉘을 작성하고있다. 그것은 꽤 별명입니다. 당신의 제안은 나쁜 것이 아닙니다.
Sv1

2
.bashrc? 왜 bash와 관련이없는 것들로 혼란스럽게할까요? 내가하는 일은 각 명령 세트에 대한 개별 스크립트를 작성하고 ~/scripts디렉토리에 모두 넣는 것 입니다. 그런 다음 전체 ~/scripts를 내 PATH이름에 추가하면 필요할 때 이름으로 전화 할 수 있습니다.
타렉 파델

4
그런 다음 .bashrc에 넣지 마십시오. ~ / bin에 스크립트를 작성하고 PATH에 있는지 확인하십시오.
tripleee

2

열을 수동으로 선택해도 괜찮다면 pick을 사용하면 매우 빠를 수 있습니다 .

svn st | pick | xargs rm

두 번째 열의 셀로 이동하여을 누른 c다음enter


나는 당신이 언급 한 "pick"도구를 시험해 보았고 나는 그것을 좋아한다. 선택한 열을 인쇄하고 싶지만 원하는 열을 얻기 위해 "awk '{print $ 3}'"을 입력하고 싶지 않은 많은 상황에 매우 유용합니다. 불행히도 이름은 다른 "pick"도구와 충돌합니다.이 도구는 "apt install pick"으로 설치할 수 있습니다. 따라서 도구 이름을 시스템에서 "pickk"으로 바꾸고 계속 사용하려고합니다. 참조를 게시 해 주셔서 감사합니다.
윌리엄 염료

1

파일 경로가 svn st 출력의 두 번째 열에있을 필요는 없습니다. 예를 들어 파일을 수정하고 속성을 수정하면 세 번째 열이됩니다.

다음에서 가능한 출력 예를 참조하십시오.

svn help st

출력 예 :

 M     wc/bar.c
A  +   wc/qax.c

처음 8자를 잘라서 다음과 같이 제안합니다.

svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done

예를 들어 100 % 확신하고 공백이있는 멋진 파일 이름을 처리하려면 xml 출력을 구문 분석해야합니다.

svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'

물론 grep / sed 대신 실제 XML 파서를 사용하고 싶을 수도 있습니다.

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