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

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

내가해야 할 일 : 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 할 수있는 방법이 있습니까?



답변

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하지만은 행의 시작 부분에 하나의 또는 콜론 다음, 그것은 말 중 하나의 경우에만 경우에만 줄 또는 그 뒤에 콜론이옵니다.


답변

다음을 사용하여 확장 정규식을 사용할 수 있습니다 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에서 테스트되었습니다.


답변

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

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


답변

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

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

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


답변

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

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


답변

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

grep '\B/opt/gnome'


답변

에 거의 노력을 기울이지 않고이 작업을 안정적으로 수행 할 수 있습니다 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