줄의 시작 또는 중간에 패턴을 잡기


9

나는이 문제가 생각보다 조금 덜 무해하다고 생각하는 것으로 시작하겠습니다.

내가해야 할 일 : PATH 환경 변수 내의 폴더를 확인하십시오. 그것은 시작이나 어딘가에있을 수 있습니다. 해당 폴더가 있는지 확인하기 만하면됩니다.

내 문제의 예-사용하자 /opt/gnome.


시나리오 1 : 폴더가 PATH 시작 부분에 없습니다

# echo "$PATH"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome

# echo "$PATH" | grep ":/opt/gnome"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome

grep이 잡히지 않도록 충분히 구체적이어야합니다 /var/opt/gnome. 따라서 결장.


시나리오 2 : 폴더가 PATH 시작에 있습니다.

# echo "$PATH"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome

# echo "$PATH" | grep "^/opt/gnome"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome

이것은 내 문제입니다.이 폴더로 콜론이나 줄 시작을 검색해야합니다. 내가하고 싶은 것은이 두 대괄호 표현 중 하나입니다.

# echo $PATH | grep "[^:]/opt/gnome"
# echo $PATH | grep "[:^]/opt/gnome"

하지만 [^[:자신의 의미를 가지고있다. 따라서 위의 두 명령이 작동하지 않습니다.

이 두 시나리오를 한 명령으로 grep 할 수있는 방법이 있습니까?


당신이 grepping하지 않을 이후 : 코스타스의 대답에 질의 댓글이 너무 질문에 적용됩니다 /opt/gnome:또는 /opt/gnome$, 당신은 발견 할 것이다 /opt/gnome-foo/opt/gnome/bar.
Scott

@Scott-당신이 당신의 경기에 개입 공간을 포함하는 한, 당신은 항상 그러한 합병증없이 줄의 머리와 꼬리에 문자열을 고정 할 수 있습니다. 마찬가지로grep '^\(any number of other matches:*:\)*my match\(:.*\)*$'
mikeserv

답변:


10

PATH파일에서 무언가를 찾는 것과는 달리 환경 변수 의 내용을 확인하는 grep경우 잘못된 도구입니다. 쉘에서하는 것이 더 쉽고 빠르며 읽기 쉽다.

bash, ksh 및 zsh에서 :

if [[ :$PATH: = *:/opt/gnome:* ]]; then
 : # already there
else
  PATH=$PATH:/opt/gnome
fi

포터블 :

case :$PATH: in
  *:/opt/gnome:*) :;; # already there
  *) PATH=$PATH:/opt/gnome;;
esac

:$PATH:오히려 사용 $PATH; 이런 식으로 구성 요소는 시작 또는 끝에 있더라도 검색 문자열에서 항상 콜론으로 둘러싸입니다 $PATH.

당신이 파일의 라인을 통해 검색하는 경우, 당신은 (즉, 필요로하는 확장 된 정규 표현식을 사용할 수 있습니다 grep -E) (^|:)/opt/gnome($|:)일치 /opt/gnome하지만은 행의 시작 부분에 하나의 또는 콜론 다음, 그것은 말 중 하나의 경우에만 경우에만 줄 또는 그 뒤에 콜론이옵니다.


8

다음을 사용하여 확장 정규식을 사용할 수 있습니다 grep -E

오 탐지를 피하려면 경로의 시작과 끝을 일치시켜야합니다.

처음에 인스턴스와 일치합니다.

$ TEST=/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome

중간에있는 인스턴스와도 일치합니다.

$ TEST=/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"
/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome

오 탐지 피하기 :

$ TEST="/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta"
$ echo $TEST | grep -E "(:|^)/opt/gnome(:|$)"

일치하는 항목이 없습니다.

작고 우아합니다. 데비안 7에서 테스트되었습니다.


1
egrep사용되지 않는 사용이다 grep -E(자료 : man grep)
안톤

고마워, 매력처럼 작동합니다! -w 옵션이 조금 더 간단하다고 생각하기 때문에 대답으로 선택하지 않았습니다. 내가 원래 상상했던 것보다 훨씬 간단합니다!
JamesL

3
경고. 이 -w옵션에는 몇 가지 문제가 있습니다. 숫자, 문자 및 밑줄 만 "단어"로 간주됩니다. 따라서 특이하지만 가능한 문자가 실패합니다. 예 echo '/sbin:/usr/sbin:/var-/opt/gnome' | grep -w "/opt/gnome"echo '/sbin:/usr/sbin:/var./opt/gnome' | grep -w "/opt/gnome". 그것들은 잘못된 결과를 제공합니다.
Luis Antolín Cano

1
귀하는 올바른 길을 가고 있지만 여전히 오 탐지가 있습니다 : /opt/gnome/somethingelse.
질 'SO-정지 존재 악마'

1
맞습니다. 우리는 시작뿐만 아니라 끝까지도 명시 적으로 고려해야합니다. 이것이 문제를 해결한다고 생각합니다 echo "/home/bob/opt/gnome:/opt/gnome/somethingelse:/opt/gnome-beta" | grep -E "(:|^)/opt/gnome(:|$)". 답변 수정.
루이스 안 톨린 카노

7

당신이 결혼하지 않은 경우에 grep, 당신은 awk에 기록을 사용 하고 분리 할 수 있습니다:

awk 'BEGIN {RS=":"} /^\/opt\/gnome$/'

5

당신은 또한 사용할 수 있습니다

echo "$PATH" | tr ':' '\n' | grep -x "/opt/gnome"

경로 변수를 별도의 줄 (경로당 하나)로 분할하므로 grep -x정확한 결과를 찾을 수 있습니다. 이것은 물론 추가 프로세스가 필요하다는 단점이 있습니다 tr. 폴더 이름에 PATH개행 문자 가 포함되어 있으면 작동하지 않습니다 .


2

나는 대답하기에 충분하다는 것을 모른다.

grep -w "/opt/gnome"

당신의 필요를 만족시킬 것입니다.

echo '/sbin:/usr/sbin:/opt/gnome:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome
echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep -w "/opt/gnome" -o
/opt/gnome

그러나

echo '/opt/gnome:/sbin:/usr/sbin:/var/opt/gnome' | grep "/opt/gnome" -o
/opt/gnome
/opt/gnome

콜론은 단어가 아닌 문자이기 때문에 완벽하게 작동합니다. 감사!
JamesL

@ Sman865 다른 이유가 있습니다. 왜냐하면 /단어의 일부가 아니기 때문 r입니다.
Costas

2
경고. 내 대답에 대한 의견에서 말했듯이. 단어가 아닌 문자 인 디렉토리 이름에 유효한 문자가 있습니다. 그 결과 잘못된 결과가 발생합니다. 디렉토리 이름을 끝내는 것은 일반적이지 않지만 발생할 수 있습니다.
Luis Antolín Cano

4
@ Sman865 False positives : /opt/gnome-beta,, /home/bob/opt/gnome
Gilles 'SO- 악의 존재 중지

경우 작동하지 : grep -w /usr/local -o <<< /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games------/usr/local /usr/local /usr/local
pabouk

0

선택합니다 /opt/gnome(새로운 라인, 비 단어 문자로 둘러싸인 :, /등)이 하나를 시도해보십시오 :

grep '\B/opt/gnome'

0

에 거의 노력을 기울이지 않고이 작업을 안정적으로 수행 할 수 있습니다 grep. 광범위하게 사용 가능하고 이미 많은 솔루션이 제공되는 확장을 이용할 수 있지만 기본 정규 표현식을 사용하더라도 쉽게 수행 할 수는 있지만 처음에는 직관적이지 않을 수 있습니다.

기본 정규 표현식과 함께 grep-항상 머리와 꼬리의 두 가지 신뢰할 수있는 앵커가 있습니다. 다음 과 같이 라인상의 위치에 관계없이 두 가지 모두에 일치 항목을 고정시킬 수 있습니다 .

grep '^\(ignore case, delimiter\)*match\(delimiter, ignore case\)*$'

grep\(grouped\)같은 방식으로 다음 구분 기호와 명시 적으로 일치하고 일치하는 꼬리에서 줄의 꼬리까지 발생 해야하는 만큼 많은 하위 표현식 이 줄의 머리 에서 일치합니다. 사용자의 명시 적 일치가 일치하지 않는 경우 명시 적으로 는 실패하고 아무것도 인쇄하지 않습니다.

예를 들어 다음과 같이 할 수 있습니다.

grep '^\(.*:\)*/opt/gnome\(:.*\)*$'

직접 참조하십시오 :

grep '^\(.*:\)*/opt/gnome\(:.*\)*$
' <<\INPUT
/opt/gnome-beta
/opt/gnome
/home/bob/opt/gnome
:/opt/gnome:
/home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta
/opt-gnome-beta
/opt/gnomenot::::/opt/gnome
INPUT

산출

/opt/gnome
:/opt/gnome:
/home/bob/opt/gnome:/opt/gnome:/opt/gnome-beta
/opt/gnomenot::::/opt/gnome

0

당신은 가장자리 케이스를 발견했습니다 ... 줄의 시작 부분에 :를 강제로 적용하여 피할 수 있습니다 :

 echo ":$PATH" | grep ":/opt/gnome"

또는 경로가 정확한 경우 끝에 하나를 추가하여 경로가 바인드되도록하십시오.

 echo ":${PATH}:" | grep ":/opt/gnome:"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.