Bash 스크립트: 일치하는 줄에 주석 추가/제거

Bash 스크립트: 일치하는 줄에 주석 추가/제거

~/.zshrc다음 줄을 포함하는 파일이 있습니다

...
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
##export PATH="/usr/local/opt/[email protected]/bin:$PATH"
##export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
export PATH="/usr/local/opt/[email protected]/bin:$PATH"
export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
...

저는 PHP 버전(첫 번째 매개변수)과 작업(두 번째 매개변수)을 허용하는 작은 bash 스크립트를 준비 중입니다. 예를 들어 가상 명령은 다음과 같습니다.

mycommand 7.4 comment

그러면 파일에서 다음 줄만 주석 처리됩니다.

#export PATH="/usr/local/opt/[email protected]/bin:$PATH"
#export PATH="/usr/local/opt/[email protected]/sbin:$PATH"

당신이 달리면

mycommand 7.1 uncomment

다음 줄만 업데이트됩니다.

export PATH="/usr/local/opt/[email protected]/bin:$PATH"
export PATH="/usr/local/opt/[email protected]/sbin:$PATH"

sed그래서 내 질문은 .sh 스크립트의 명령이나 다른 명령을 사용하여 파일을 구문 분석하는 방법입니다 .
내 bash 스크립트는 다음과 같습니다(작동하지 않음)

# File mycommand.sh
# ...
if [[ ! -z "$1" && ! -z "$2" && "$2" = "comment" ]]; then
    # remove multi # comments if there's any
    sed -i '' 's/#*export PATH="\/usr\/local\/opt\/php@$1/export PATH="\/usr\/local\/opt\/php@$1/g'   
    # Finally add a single # comment
    sed -i '' 's/*export PATH="\/usr\/local\/opt\/php@$1/#export PATH="\/usr\/local\/opt\/php@$1/g'    
fi
if [[ ! -z "$1" && ! -z "$2" && "$2" = "uncomment" ]]; then
    # remove one or more # comments
    sed -i '' 's/#*export PATH="\/usr\/local\/opt\/php@$1/export PATH="\/usr\/local\/opt\/php@$1/g'   
fi

답변1

이는 강력하고 효율적이며 이식 가능하게 작동합니다.

#!/usr/bin/env bash

infile=~/.zshrc
tmp=$(mktemp) || exit 1

awk -v ver="$1" -v cmd="$2" '
    index($0,"php@"ver"/") {
        if      ( cmd == "comment" )   { sub(/^#*/,"#") }
        else if ( cmd == "uncomment" ) { sub(/^#+/,"")  }
        else { printf "bad cmd: %s\n", cmd | "cat>&2" }
    }
    { print }
' "$infile" > "$tmp" && mv "$tmp" "$infile"

필요한 경우 실제 입력에는 있지만 예제에는 표시되지 않은 다른 줄과의 잘못된 일치를 방지하도록 "php@"ver"/"변경 하세요."export PATH=\"/usr/local/opt/php@"ver"/"

GNU awk가 있는 경우 -i inplacetmp 파일을 수동으로 생성하는 대신 이를 사용할 수 있습니다.

답변2

사용하는 스크립트를 다음과 같이 변경해야 합니다.

if [[ ! -z "$1" && ! -z "$2" && "$2" = "comment" ]]; then
    # remove multi # comments if there's any
    sed -i "s/#*export PATH=\"\/usr\/local\/opt\/php@$1/export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
    # Finally add a single # comment
    sed -i "s/export PATH=\"\/usr\/local\/opt\/php@$1/#export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
fi
if [[ ! -z "$1" && ! -z "$2" && "$2" = "uncomment" ]]; then
    # remove one or more # comments
   sed -i "s/#*export PATH=\"\/usr\/local\/opt\/php@$1/export PATH=\"\/usr\/local\/opt\/php@$1/g" ~/.zshrc
fi

문제는 다음과 같습니다

  1. 그 뒤에는 빈 작은따옴표( '') 가 옵니다 sed -i.

  2. sed입력 파일( )을 지정하지 않았습니다 ~/.zshrc.

  3. 쉘이 변수를 먼저 확장 하도록 작은따옴표( ") 대신 큰따옴표( )를 사용해야 합니다 . 바라보다'$1이것그리고이것관련 질문.

관련 정보