if then 문과 모든 bash 스크립트

if then 문과 모든 bash 스크립트

여러 파일에서 특정 문자열을 확인한 다음 발견되면 제거하는 bash 스크립트를 작성하려고 합니다. 여기에 내가 가지고 있는 것이 있고 그것이 효과가 있을 것이라고 생각하지만 부분적으로만 가능합니다. 파일의 항목은 삭제되지만 두 번째로 실행하면 "Nothing to do..." 메시지가 표시되지 않습니다.

#!/bin/bash
files=(
        '/etc/rsyslog.conf'
        '/etc/rsyslog.d/remote.conf'
        '/etc/rsyslog.d/01-remote.conf'
)

tmpcheck="for f in ${files[*]}; do  cat $f | grep blah | wc -l; done"
#for f in ${files[*]}; do  cat $f | grep collector.acuity.com | wc -l; done

if [[ "$tmpcheck" != 1 ]];then
for f in "${files[@]}";do
                echo -e "Removing blah from $f"
                sed -i "/blah/d" "$f"
        done
                echo -e "Restarting rsyslog service"
                systemctl restart rsyslog.service
else
        echo -e "Nothing to do, blah has been removed from $f"
fi

어떤 도움이라도 큰 도움이 될 것입니다.

답변1

tmpcheck코드의 주요 문제(쌍 할당)는 다른 답변에서 지적되었습니다. 수정된/수정되지 않은 파일의 이름을 인쇄하는 것이 필수가 아니라고 가정하는 약간 다른 접근 방식은 다음과 같습니다.

if grep -q -- blah "${files[@]}"
then
    sed -i -e '/blah/d' -- "${files[@]}"
    systemctl restart rsyslog.service
else
    printf '%s\n' 'Nothing to do'
fi

여기서 주요 아이디어는 다음과 같습니다.

  • 필요한 경우가 아니면 출력을 저장하고 나중에 테스트하는 대신 복합 명령 내에서 직접 명령의 ( grep) 종료 상태를 사용하십시오.if
  • 루프에서 유틸리티를 호출하는 것은 덜 효율적입니다. 가능할 때마다 여러 파일을 인수로 사용하여 호출하는 것이 가장 좋습니다.

또한 표시되는 코드에서는 이러한 문제가 발생하지 않지만 다음을 수행합니다.

  • 옵션 닫기 태그( --)를 추가하면 비정상적인 파일 이름을 방지할 수 있습니다.
  • printf 더 안전한특히 확장된 결과를 인쇄할 때 더욱 그렇습니다 echo.

답변2

for 루프 내부의 말도 안되는 내용을 확인하고 싶다고 생각합니다. tmpcheck 변수는 필요하지 않습니다. 대신 $restartrsyslogrsyslog를 한 번만 다시 시작할 수 있습니다.

files=(
    '/etc/rsyslog.conf'
    '/etc/rsyslog.d/remote.conf'
    '/etc/rsyslog.d/01-remote.conf'
)

restartrsyslog=

for f in "${files[@]}";do
    if grep -q blah "$f"; then
        echo -e "Removing blah from $f"
        sed -i "/blah/d" "$f"
        restartrsyslog=yes
    else
        echo -e "Nothing to do, blah has been removed from $f"
    fi
done

if [[ -n $restartrsyslog ]] ; then
    echo -e "Restarting rsyslog service"
    systemctl restart rsyslog.service
fi

답변3

변수 는 tmpcheck해당 명령의 출력이 아닌 명령으로 설정되며 1과 같지 않으므로 표현식은 항상 true로 평가됩니다. $( ... )명령의 출력을 바꾸려면 이 구성을 사용해야 합니다 . 또한 파일을 반복할 필요는 없지만, 그렇게 하는 경우 ${files[*]}해당 파일을 대신 사용해서는 안 됩니다 ${files[@]}. 또한 파일을 읽을 수 있으므로 cat단일 파일로 파이프 할 필요가 없고 결과를 선택적으로 계산할 수 있으므로 파이프 로 연결할 필요도 없습니다 . 마지막으로 왜 1이 아닌지 확인하고 싶습니까 ? 2 이상이면 어떻게 되나요?grepgrepgrepwc -lgrep-ctmpcheck

이것이 당신에게 효과가 있습니까?

#!/bin/bash
files=(
    '/etc/rsyslog.conf'
    '/etc/rsyslog.d/remote.conf'
    '/etc/rsyslog.d/01-remote.conf'
)

tmpcheck=$(cat "${files[@]}" | grep -c blah)

if (($tmpcheck>=1)); then
    for f in "${files[@]}";do
        echo -e "Removing blah from $f"
        sed -i "/blah/d" "$f"
    done
    echo -e "Restarting rsyslog service"
    systemctl restart rsyslog.service
else
    echo -e "Nothing to do, blah has been removed from $f"
fi

관련 정보