Bash 파일에 문자열이 있는지 테스트하는 방법은 무엇입니까?


337

디렉토리 이름이 포함 된 파일이 있습니다.

my_list.txt :

/tmp
/var/tmp

해당 이름이 파일에 이미 존재하는 경우 디렉토리 이름을 추가하기 전에 Bash를 확인하고 싶습니다.


파일 내부의 모든 문자열을 찾으려면 FOR 루프에서 grep을 실행할 수 있습니다. unix.stackexchange.com/a/462445/43233
Noam Manos

답변:


655
grep -Fxq "$FILENAME" my_list.txt

이름이 발견되면 종료 상태는 0 (true)이고 그렇지 않으면 1 (false)입니다.

if grep -Fxq "$FILENAME" my_list.txt
then
    # code if found
else
    # code if not found
fi

설명

다음에 대한 매뉴얼 페이지grep 의 관련 섹션이 있습니다 .

grep [options] PATTERN [FILE...]

-F, --fixed-strings

        PATTERN을 줄 바꿈으로 구분 된 고정 문자열 목록으로 해석하십시오.

-x, --line-regexp

        전체 줄과 정확히 일치하는 일치 항목 만 선택하십시오.

-q, --quiet,--silent

        조용한; 표준 출력에 아무것도 쓰지 마십시오. 오류가 발견 된 경우에도 일치하는 것이 있으면 0 상태로 즉시 종료하십시오. -s또는 --no-messages옵션 도 참조하십시오 .

오류 처리

주석에서 올바르게 지적했듯이 위의 접근 방식은 오류 사례를 문자열이 발견 된 것처럼 자동으로 처리합니다. 다른 방식으로 오류를 처리하려면 -q옵션 을 생략 하고 종료 상태에 따라 오류를 감지해야합니다.

일반적으로 선택된 라인이 발견되면 종료 상태는 0이고 그렇지 않으면 1입니다. 그러나 -qor --quiet또는 --silent옵션을 사용하고 선택한 행을 찾을 수 없으면 오류가 발생한 경우 종료 상태는 2 입니다. 단, 그와 같은 프로그램에 대한 POSIX에만 위임, grep, cmp, 및 diff오류의 경우에 종료 상태가 1보다 클 수 있음; 따라서 이식성을 위해 2와의 엄격한 평등 대신이 일반적인 조건을 테스트하는 논리를 사용하는 것이 좋습니다.

의 일반 출력을 억제하려면로 grep리디렉션 할 수 있습니다 /dev/null. 표준 오류는 방향이 지정되지 않으므로 grep인쇄 될 수 있는 오류 메시지는 원하는대로 콘솔에 표시됩니다.

세 가지 경우를 처리하기 위해 case명령문을 사용할 수 있습니다 .

case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
  0)
    # code if found
    ;;
  1)
    # code if not found
    ;;
  *)
    # code if an error occurred
    ;;
esac

2
bash 스크립트 에서이 명령을 실행하면 변수에 0 또는 1을 잡는 방법은 무엇입니까?
Toren

6
@Toren 가장 최근의 종료 상태는을 사용하여 액세스 할 수 있습니다 $?. if업데이트 된 답변에 표시된대로 명령문 과 함께 grep 명령을 사용할 수도 있습니다 .
Shawn Chin

5
당신은 사용할 수 있습니다 grep -Fqx "$FILENAME"당신은 변수 내용에서 정규식 문자에 대해 걱정할 필요가 없습니다 당신은 검색 문자열에서 사용 할 필요가 없습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

4
이 대답을보고있는 사람들을위한 몇 가지 참고 사항 : 1) bash에서 0은 항상 true이고 다른 것은 항상 false입니다. 2) 전체 줄을 정확하게 일치 시키려면 -x 플래그 만 사용하십시오. 문자열이 파일에 있는지 확인하려면 해당 문자열을 해제하십시오. 문자열이 정확하게 존재하지만 전체 줄을 반드시 일치시키지 않으면 서 (즉, 전체 단어로) 찾으려면 -w를 사용하십시오.
Schmick

1
나는 -q / --silent그것이 필요 하지 않습니까 ? 오류가 발생하더라도 bash를 "모두 양호"로 잘못 표시합니다. 내가 제대로 알았다면 이 경우 결함이있는 개념 인 것 같습니다.
redanimalwar

90

다음 해결책에 관하여 :

grep -Fxq "$FILENAME" my_list.txt

-Fxq평범한 영어로 무엇을 의미 하는지 궁금해하는 경우 :

  • F: PATTERN 해석 방법에 영향을줍니다 (정규식 대신 고정 문자열)
  • x: 전체 라인 일치
  • q: hh ... 최소한의 인쇄

man 파일에서 :

-F, --fixed-strings
    Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of which is to be matched.
    (-F is specified by POSIX.)
-x, --line-regexp
    Select only those matches that exactly match the whole line.  (-x is specified by POSIX.)
-q, --quiet, --silent
    Quiet; do not write anything to standard output.  Exit immediately with zero status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages option.  (-q is specified by
          POSIX.)

5
-F는 파일 처리에 영향을 미치지 않으며 PATTERN의 해석 방법에 영향을줍니다. 일반적으로 PATTERN은 정규식으로 해석되지만 -F를 사용하면 고정 문자열로 해석됩니다.
Adam S

41

내 마음에 세 가지 방법 :

1) 경로의 이름에 대한 간단한 테스트 (이것이 귀하의 경우인지 확실하지 않습니다)

ls -a "path" | grep "name"


2) 파일에서 문자열에 대한 간단한 테스트

grep -R "string" "filepath"


3) 정규식을 사용하는 더 긴 bash 스크립트 :

#!/bin/bash

declare file="content.txt"
declare regex="\s+string\s+"

declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
    then
        echo "found"
    else
        echo "not found"
fi

exit

이렇게해야 빨리 당신이있는 경우 파일에 여러 개의 문자열을 테스트 할 수 있는 cicle에서 정규 표현식을 변경하는 예를 들어 루프를 사용하여 콘텐츠.


10
$ file_contenet 앞뒤에 공백이 필요한 이유는 무엇입니까?
EminezArtus 2019

빠른 솔루션과보다 일반적인 솔루션을위한 1 플러스
Wassadamo

19

더 간단한 방법 :

if grep "$filename" my_list.txt > /dev/null
then
   ... found
else
   ... not found
fi

팁 : /dev/null명령의 종료 상태를 원하지만 출력이 아닌 경우에 보내 십시오.


1
또는 다음 -q과 같은 것을 사용하십시오 --quiet:)
rogerdpack

에 동의 -q여기에 가장 좋은 대답 하고 4 위입니다. 이 세상에는 정의가 없습니다.
tatsu

14

가장 쉽고 간단한 방법은 다음과 같습니다.

isInFile=$(cat file.txt | grep -c "string")


if [ $isInFile -eq 0 ]; then
   #string not contained in file
else
   #string is in file at least once
fi

grep -c는 파일에서 문자열이 몇 번이나 발생했는지를 반환합니다.


5

귀하의 질문을 올바르게 이해했다면 필요한 일을해야합니다.

  1. $ check 변수를 통해 추가하려는 디렉토리를 지정할 수 있습니다
  2. 디렉토리가 이미 목록에있는 경우 출력은 "dir already registered"입니다.
  3. 디렉토리가 아직 목록에 없으면 my_list.txt에 추가됩니다.

한 줄에 :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt


grep의 출력을 테스트 할 필요는 없습니다 . Thomas가 그의 답변 에서처럼 grep -qgrep을 직접 사용 하고 호출 할 수 있습니다 if. 또한 질문에는 디렉토리를 목록에 추가하기 전에 디렉토리가 존재하는지 확인하는 것이 포함되어 있지 않습니다 (결국 삭제 된 디렉토리 목록 일 수 있음).
sorpigal

예제 스크립트를 제거했지만 Thomas가 제공 한 답변에 아무것도 추가하지 않았습니다.
lecodesportif

3

한 줄의 존재 여부 만 확인하려면 파일을 만들 필요가 없습니다. 예 :

if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
  # code for if it exists
else
  # code for if it does not exist
fi  

3

fgrep를 사용하는 내 버전

  FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
  if [ $FOUND -eq 0 ]; then
    echo "Not able to find"
  else
    echo "able to find"     
  fi  

-c옵션 이 보이지 않습니다fgrep --help
Nam G VU

3
grep -E "(string)" /path/to/file || echo "no match found"

-E 옵션은 grep을 정규 표현식으로 사용합니다


1

@Thomas의 솔루션은 어떤 이유로 든 작동하지 않지만 특수 문자와 공백으로 더 긴 문자열을 사용하므로 다음과 같이 매개 변수를 변경했습니다.

if grep -Fxq 'string you want to find' "/path/to/file"; then
    echo "Found"
else
    echo "Not found"
fi

누군가에게 도움이되기를 바랍니다.



0
grep -Fxq "String to be found" | ls -a
  • grep은 내용을 확인하는 데 도움이됩니다
  • ls는 모든 파일을 나열합니다

@ TomWiggers 나는 똑같은 것을 시도했고 그것은 나를 위해 일했다.
Shinoy Shaji

-1
if grep -q "$Filename$" my_list.txt
   then
     echo "exist"
else 
     echo "not exist"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.