스크립트가 여러 번 실행되는 경우 bash 스크립트를 한 번만 에코하는 도구

스크립트가 여러 번 실행되는 경우 bash 스크립트를 한 번만 에코하는 도구

편집: 불행하게도 반대표를 받았습니다. 이것은 아니다내 거질문. 이것이 Linux가 원하는 작업 방식이며, 임시적이고 일관되지 않은 설치 시나리오를 사용하는 수많은 도구가 있습니다. 제가 이 질문을 하는 이유는 한 번만 작동하고 모든 것이 처음에 완벽하게 작동하는 서툴게 작성된 스크립트를 생성, 채택 및 유지 관리하지 않고도 올바른 일을 하고 싶기 때문입니다.


스크립트가 특정 .bashrc파일이나 유사한 파일에 무언가를 반영해야 하는 경우가 종종 있습니다. 이는 설치 스크립트의 맥락에서도 자주 발생하므로 이러한 파일 쓰기는 오직한 번설치 스크립트는 실패 또는 편집 시 여러 번 실행될 수 있기 때문입니다.

구체적인 예를 들자면,설치하다asdf, 다음 내용을 파일에 작성해야 합니다 ~/.bashrc.

# asdf
. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"

설치 스크립트에서 이를 사용 하고 echo스크립트가 여러 번 실행되면 위의 세 줄이 원하는 만큼 반복됩니다. 이전에 스크립트에서 작성한 솔루션을 사용하면 다음과 같은 일이 발생합니다.

# Install asdf
sudo apt-get install curl git -y
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
echo $'\n# asdf' >> ~/.bashrc
echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
source ~/.bashrc

이제 적절한 스크립팅 언어(예: PowerShell 또는 스크립팅 가능한 프로그래밍 언어)를 사용하여 이를 처리할 수 있지만 순수 스크립팅에서 이를 처리하는 가장 좋은 방법은 무엇입니까 bash? 이 문제를 해결하는 데 도움이 되는 도구가 있습니까? 나는 함께 묶을 수 있는 몇 가지 마법 유틸리티가 있다고 가정하고 있으며 이는 허용 가능한 답변이지만 도구가 이 문제에 더 집중할수록 더 좋습니다.

해결책이 있었으면 좋겠어무엇좋다:

# <asdf-begin>
. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"
# <asdf-end>

부분 사이에 실제 작업을 수행하는 스크립트 부분이 있는 경우 보너스 포인트변화, 그런 다음 스크립트를 다시 실행하면 완전히 새로운 블록을 작성하는 대신 시작 줄과 끝 줄 사이가 업데이트됩니다.

답변1

원래 문제를 해결하는 방법을 보여주기 전에 먼저 올바른 방법을 보여 드리겠습니다.

루트 권한이 있는 경우 이 목적으로 사용되는 디렉터리에 파일을 간단히 설치할 수 있습니다. 그러면 모든 사용자에 대해 asdf가 설치됩니다.

cp ~/.asdf/completions/asdf.bash /usr/share/bash-completion/completions/asdf
cp ~/.asdf/asdf.sh /etc/profile.d/asdf.sh

루트 액세스 권한이 없는 경우 ~/.local/share/bash-completion/completions/아래 단계에 따라 완료 스크립트를 설치하세요.사용자 정의 bash_completion.d 스크립트의 표준 위치는 무엇입니까?( bash-completion설치가 필요합니다.) 표준 사용자에 해당하는 항목은 모르지만 /etc/profile.d/쉽게 직접 만들 수 있습니다. /etc/profile여기에는 다음 줄이 포함되어야 합니다.

# Load profiles from /etc/profile.d
if test -d /etc/profile.d/; then
    for profile in /etc/profile.d/*.sh; do
        test -r "$profile" && . "$profile"
    done
    unset profile
fi

여기서 영감을 얻어 다음 줄을 입력해 보겠습니다 ~/.profile.

if test -d ~/profile.d/; then
    for profile in ~/profile.d/*.sh; do
        test -r "$profile" && . "$profile"
    done
    unset profile
fi

그러면 간단하게 할 수 있습니다 cp ~/.asdf/asdf.sh ~/profile.d/asdf.sh. asdf가 이미 설치되어 있어도 작동합니다.

그런데 수동으로 소프트웨어를 설치하는 대신 Linux 배포판의 패키지 관리자를 사용하는 것이 좋습니다. 패키지 작성은 어렵지 않습니다. 바라보다비난하다기존 패키지의 경우여기아치 리눅스의 예.

원래 문제를 해결하세요.

if grep -wq 'asdf.sh' ~/.bashrc; then
    : # asdf already installed, do nothing
else
    echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
fi

<asdf-begin>보너스 포인트를 얻으려면 GNU sed를 사용하여 먼저 와 사이의 줄을 삭제한 <asdf-end>다음 업데이트된 블록을 작성할 수 있습니다.

sed -i '/<asdf-begin>/,/<asdf-end>/d' ~/.bashrc
cat <<'EOF' >>~/.bashrc
# <asdf-begin>
. "$HOME/.asdf/asdf.sh"
# <asdf-end>
EOF

답변2

솔직히, 나는 문제가 되는 대사를 찾아 헤맬 것입니다. 거기에 있으면 아무 것도 하지 말고, 없으면 줄을 추가하십시오.

전임자:

line1=$(grep "asdf.bash" ~/.bashrc)
if [ ! -z "$line1" ];
then
  echo "Lines are present, continue"
else
  echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
  echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
fi

물론, 이것은 여러 줄을 grep하기 위해 함께 묶을 수 있습니다. 또는 3줄이 모두 포함되어 있다는 것을 알 수 있도록 한 줄만 grep하면 충분합니다.

관련 정보