grep 출력을 CD의 경로로 사용하는 방법은 무엇입니까?


9

명령에 grep인수로 출력을 파이프하는 방법은 cd무엇입니까?

예를 들면 다음과 같습니다.

[root@xxx xxx]# pip install django | grep '/usr.*'  
Requirement already satisfied (use --upgrade to upgrade): django in   /usr/lib64/python2.7/site-packages

여기 /usr/lib64/python2.7/site-packages에 강조 표시되어 있으며이 문자열을에 전달하고 싶습니다 cd.

답변:


16

Bash의 명령 대체를 사용 하면 일치하는 부분 만 선택하려면 grep이 $()필요합니다 -o.

cd "$(pip install django | grep -o '/usr.*')"

이 경우 도망 치지 만 쉘이 공백에서 단어 분할 을 수행하지 않도록 명령 대체를 큰 따옴표로 묶어야합니다 (기본적으로 공백, 탭 및 줄 바꿈 IFS은 경우 에 따라 변수에 따라 다름 bash).


9

당신이 무엇을하고 무엇 pip을 출력 할 것인지 미리 알지 못한다면 , 당신은 grep다른 것 이외의 것을 결정할 수도 있습니다 /usr.*.

당신이 알고있는 경우 와 디렉토리 시작/usr (그리고 출력의 라인의 끝에 나타납니다 pip, 그리고 그 /usr디렉토리의 이름 앞에 선 아무 곳이나 표시되지 않습니다), 그 다음은 좋은 선택이다; heemayl의 대답 이 방법을 알려줍니다.

시작 하는 이유/usr 는 명령을 실행하고 변경하려는 디렉토리를 알고 있기 때문에 명령을 실행하는 더 간단한 해결책을 제안합니다 cd /usr/lib64/python2.7/site-packages. 탭 완성 기능 을 사용하지 않아도 타이핑이 줄어 듭니다 .

그렇지 않으면 구문 분석되는 출력에 대해 알고있는 내용에 따라 다른 정규 표현식을 선택할 수 있습니다. 아래의 모든 대안은 여전히 ​​디렉토리 이름이 줄 끝에 있다고 가정하지만 다른 가정은 다릅니다.

당신이 알고있는 경우에 디렉토리 이름은 절대 (즉,로 시작 /) 와 더 /디렉토리 이름 앞에 줄에 나타납니다은 , 당신은에서와 같은 정규 표현식을 사용할 수 없습니다 heemayl의 대답 만에 /대신 /usr:

cd "$(pip install django | grep -o '/.*')"

이것은 모든 문자 ( ) 의 /0 이상 ( *) 과 일치합니다 ..

당신이 알고있는 경우에 디렉토리 이름이 더 수평 공백이 없습니다 (공백이나 탭)과 라인의 끝에 나타납니다 , 당신은 사용할 수 있습니다 :

cd "$(pip install django | grep -oP '[^\h]+$')"

여기서는 약어 (for )가 동일한 확장 정규 표현식 ( ) 보다 타이핑하고 읽기가 더 쉽기 때문에 Perl 정규 표현식 ( -P)을 사용 했습니다 . 이것은 하나 이상의 (일치 ) 문자 클래스 (어떤 문자 입니다) 하지 ( ) 공백이나 탭 ( ).\h[:blank:]-E+[ ]^\h

당신이 t를 알고 있다면 그는 디렉토리 이름은 바로 앞에는 in수평 공백으로 둘러싸인 (즉, 왼쪽과 오른쪽은 공백으로 모두 채워), 그리고 이의 그러한 사건이다 in라인에가 , 당신은 사용할 수 있습니다 :

cd "$(pip install django | grep -oP '\hin\h+\K.+')"

이 용도는 제로 폭 긍정적 인 모습 숨김 주장 ( \K) 하나 개 이상의 문자 (일치하는 .+공백이나 탭 (뒤에 표시) \h) in, 또 다른 하나 이상의 공백 또는 탭 ( \h+실제로는 포함하지 않고,) in와 공백 경기에서 그것을 둘러싼. 둘러보기 어설 션 은 Perl 정규식의 기능입니다.

패턴 도 효과가 있었지만 존재하는 수에 관계없이 이전에 하나의 공백 만 찾으면됩니다 . 대조적으로, 우리는 이후의 모든 공백 과 일치해야합니다. 그렇지 않으면 무시되지 않으며 디렉토리 이름의 일부로 일치됩니다.\h+in\h+\K.+inin\K

디렉토리 이름 바로 앞에 행의 마지막in 공백가로 공백 오는 것을 알고 있으면 다음을 사용할 수 있습니다.

set +H
cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')"
set -H

너비가 0 인 양수 룩 어설 션 자체에는 너비가 0 인 음수 룩 어스 어설 션 ( (?! ))이 포함됩니다.

!어려울하는 등의 방법으로 나타납니다 탈출 우아; 내가 전달하기 전에 쉘 히스토리 확장 을 트리거하지 않도록하는 데 사용한 방법 은 명령을 실행하기 전에 grep히스토리 확장을 일시적으로 사용 안함으로 설정 한 다음 나중에 set +H다시 사용 가능하게하는 것입니다 ( set -H). 스크립트에서 이것을 사용하고 스크립트에이 포함되어 있지 않은 set -H경우, 쉘이 대화식으로 실행될 때만 히스토리 확장이 자동으로 활성화되므로이를 수행 할 필요가 없습니다.

마지막으로, 참고 이들 중 아무도 없으며 것을 heemayl의 대답은 , 실제의 출력 배관된다 grep에을 cd(의 출력 불구하고 pip여전히에 파이프되고있다 grep). 파이프 대신 이 작업에 적합한 도구는 명령 대체 입니다.


물론, 기술 을 얻으려면 쉘은 내부적으로 파이프를 사용하여 명령 출력을 읽습니다.
Random832

@ Random832 좋은 점-이 점을 고려하여 약간 편집했습니다. Btw, 명령 대체에서 "후드 아래"파이프를 사용할 수 있는지 알고 있습니까? 아니면 다른 미래 버전의 bash에서 잠재적으로 다르게 수행 될 수있는 구현 세부 사항입니까? (물론 실제로 는 그것이 최선의 방법이라는 것을 알고 있으므로 다르게 구현되지는 않습니다.)
Eliah Kagan

1
아닙니다. 이론적으로 쉘이 이름이 지정된 fifo 또는 temp 파일을 사용할 수는 있지만 보장 할 수는 없습니다.
Random832

역사 확장에 대해 확신하십니까? 그것을 막을 수있는 유일한 문자는 ` and '`이며 grep 표현식 주위에 작은 따옴표를 사용했습니다.
muru

1
@muru 예, 확장되었습니다. 나는 눈치 채지 못했지만 그것을 테스트했을 때 알았습니다. 은 !거기 인용되지 '는 AS, -quotes '-quotes 자체가 인용이다. 이 명령의 복잡성으로 인해 효과를 잘못 예측하기가 쉽지만 확장 순서 ( !초기) 로 인해x=foo; echo "'$x'" (-> 'foo') 와 같이 작동 합니다. 외부 제거 "-quotes하는 원인이 !'-quoted 역사 확장을 방지하지만, 다음 cd 디렉토리의 이름에 공백이있는 경우 실패합니다.
Eliah Kagan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.