grep 명령으로 문자열 검색을 if 문에 넣는 방법?


11

두 개의 파일에서 여러 문자열을 검색하고 싶습니다. 두 파일에서 하나의 문자열이 발견되면 무언가를 만드십시오. 하나의 파일에서만 하나의 문자열이 발견되면 다른 것을 만드십시오.

내 명령은 다음과 같습니다.

####This is for the affirmative sentence in both files
if grep -qw "$users" "$file1" && grep -qw "$users" "$file2"; then

####This is for the affirmative sentence in only one file, and negative for the other one
if grep -qw "$users" "$file1" ! grep -qw "$users" "$file2"; then

진술을 거부하고 확인하는 올바른 방법입니까? pd KSH 셸을 사용하고 있습니다.

미리 감사드립니다.

답변:


11

이 시도:

if grep -wq -- "$user" "$file1" && grep -wq -- "$user" "$file2" ; then
   echo "string avail in both files"
elif grep -wq -- "$user" "$file1" "$file2"; then
   echo "string avail in only one file"
fi
  • grep 여러 파일에서 패턴을 검색 할 수 있으므로 OR / NOT 연산자를 사용할 필요가 없습니다.

각 명령에서 "-wq"와 "-qw"사이에 최소한의 차이가 있습니까?
Mareyes

2
두 가지 모두 grep에 -q 및 -w 옵션을 제공합니다.
glenn jackman

3
변수 확장에 따옴표가없는 이유는 무엇입니까?
D. 벤 Knoble

@ D.BenKnoble : "$ user" "$ file1"이 맞습니까?
Mareyes

1
@Mareyes 예 맞습니다
D. Ben Knoble

13

다른 옵션 :

grep -qw -- "$users" "$file1"; in_file1=$?
grep -qw -- "$users" "$file2"; in_file2=$?

case "${in_file1},${in_file2}" in
    0,0) echo found in both files ;;
    0,*) echo only in file1 ;;
    *,0) echo only in file2 ;;
      *) echo in neither file ;;
esac

선택적인 방법에 대해 감사합니다. 충분히 잘 작동합니다 !! 내가 가지고있는 다른 스크립트에서 완벽하게 작동합니다.
Mareyes

좋은 아이디어야! 항상 배우기.
Joe

7
n=0

#Or if you have more files to check, you can put your while here. 
grep -qw -- "$users" "$file1" && ((n++))
grep -qw -- "$users" "$file2" && ((n++))

case $n in 
   1) 
       echo "Only one file with the string"
    ;;
   2)
       echo "The two files are with the string"
   ;;
   0)
       echo "No one file with the string"
   ;;
   *)
       echo "Strange..."
   ;;
esac 

참고 : ((n++))ksh 확장자입니다 ( zsh및로 지원됨 bash). POSIX sh구문 에서는 n=$((n + 1))대신 필요 합니다.


죄송합니다. ((n ++)) 대신 $ ((n ++))를 입력하고있었습니다. 잊다.
Luciano Andress Martini

1
참고 n=$((n++))때문에 n의 값을 변경하지 않을 것 n++입니다 증가 :가 반환 현재 값 , N의를 다음 단위로 N; 그런 다음 변수를 원래 n 인 반환 값으로 설정하십시오.
glenn jackman

파일 이름에 줄 바꿈이 포함되어 있지 않다고 가정하고을 local IFS=$'\n'; matches=( $(grep -lw "$users" "$file1" "$file2") )사용하십시오 case "${#matches[@]" in. @glenn :이 아이디어는의 여러 호출을 피하기 위해 귀하의 답변에도 적용됩니다 grep. 그것을 배관하는 grep -l | wc -l것도 효과가 있습니다.
Peter Cordes

@Peter는 별도의 답변 IMO로 쓸만한 가치가 있습니다.
Stephen Kitt

@ StephenKitt : 임의의 파일 이름 문자를 처리하는 방탄 방법을 찾을 수 없기 때문에 갈 수 없었습니다. 그러나 당신은 그만한 가치가 있다고 생각하기 때문에 어쨌든 그것을 썼습니다.
Peter Cordes

2

파일 이름에 줄 바꿈이 없으면 grepgrep이 일치하는 파일 이름을 인쇄하고 결과를 계산하여 여러 번의 호출을 피할 수 있습니다 .

 local IFS=$'\n'    # inside a function.  Otherwise use some other way to save/restore IFS
 matches=( $(grep -lw "$users" "$file1" "$file2") )

일치 횟수는입니다 "${#matches[@]}".

grep --null -lw여기 에 사용하는 방법이있을 수 있지만 출력을 구문 분석하는 방법을 모르겠습니다 . Bash var=( array elements )\0대신 구분 기호 를 사용하는 방법이 없습니다 \n. bash의 mapfile내장 기능이 가능할까요? 그러나 구분 기호를로 지정하기 때문에 아마도 아닐 것입니다 -d string.


가능 count=$(grep -l | wc -l)하지만 두 개의 외부 프로세스가 있으므로 grep두 파일을 개별적으로 실행할 수도 있습니다 . ( 개별 프로세스를 시작하기 위해 포크 + 실행 + 동적 링커와 비교할 때 시작 오버 헤드 grep와 의 차이 wc는 적습니다.)

또한 일치 하는 파일을 wc -l찾지 못합니다 .


배열에서 결과를 캡처하면 이미 원하는 결과이거나 정확히 1 개의 일치 항목이있는 경우 첫 번째 입력인지 여부를 확인할 수 있습니다.

local IFS=$'\n'    # inside a function.  Otherwise use some other way to save/restore IFS
matches=( $(grep -lw "$users" "$file1" "$file2") )

# print the matching filenames
[[ -n $matches ]] && printf  'match in %s\n'  "${matches[@]}"

# figure out which input position the name came from, if there's exactly 1.
if [[ "${#matches[@]" -eq 1 ]]; then
    if [[ $matches == "$file1" ]];then
        echo "match in file1"
    else
        echo "match in file2"
    fi
fi

$matches${matches[0]}첫 번째 배열 요소의 약어입니다 .


@StephenKitt : 나는 의미 -z하지 -0, 죄송합니다. 예 \0, 대답에서 이미 언급 한 것처럼 파일 이름을 구분하여 grep 할 수는 있지만 어떻게 bash 를 구문 분석 할 수 있습니까? bash를 설정 IFS=$'\0'하거나 기본적으로 find -print0스타일 출력을 사용하여 bash로 직접 다른 작업을 수행 할 수 없습니다 .
Peter Cordes

예, 너무 빨리 읽고 해당 단락이 누락되어 생각을하지 못했습니다 (그래서 내 의견을 삭제했습니다). 방법이있을 수는 있지만 지금은 생각할 수 없으며 grep어쨌든 처리해야 할 몇 가지가있을 때 솔루션을 너무 복잡하게 만들 가치가 없습니다 .
Stephen Kitt

1
mapfile -d $'\0'일종의 작품이지만 줄 바꿈을 공백으로 바꿉니다 (조정하지 않았습니다 IFS).
Stephen Kitt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.