sed를 사용하여 매우 복잡한 표현식 관리

sed를 사용하여 매우 복잡한 표현식 관리

이 줄을 대체할 스크립트를 작성하려고 합니다.

 [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "

다음 줄을 사용하세요.

# [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "

그러면 새 줄이 추가됩니다.

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \D{%T} \W]\\$ "

파일 로 /etc/bashrc. 기본적으로 스크립트가 이전 설정에 주석을 달고 프롬프트의 사용자 이름 옆에 타임스탬프(새 설정)를 추가하기를 원합니다. 나는 다음과 같이 첫 번째 부분을 수행하려고합니다.

pattern=' [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "'
sudo sed 's/${pattern}/#${pattern}/' < /etc/bashrc 

하지만 작동하지 않습니다. 문자열의 특수 문자 때문인 것 같습니다. 하지만 어떤 문자를 이스케이프해야 하는지 잘 모르겠습니다. 마지막 부분은 다음과 같아야 합니다.

sed -i '  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \D{%T} \W]\\$ "' /etc/bashrc

몇 가지 안내가 제공됩니다.

감사해요

답변1

  1. 스크립트의 작은따옴표는 확장을 sed방지합니다 ${pattern}. 큰따옴표를 사용해야 합니다(그러나 이로 인해 언급된 특수 문자 문제가 발생합니다).
  2. sed주어진 행의 주소 지정을 충분히 사용하여 식별한 후 다음과 같은 주석을 삽입하십시오./^ *\[ *"$PS1 =/s/^/#/
  3. a명령을 사용하여 sed주어진 줄을 추가합니다 .

귀하의 경우에는 줄에 뭔가를 추가하고 싶기 때문에

sed 's/\( *\[ "$PS1" = "..s-..v...$ " \] && PS1="\[[email protected] \)\(.W]..$ "\)/#\1\2\
\1\\D{%T} \2/' /etc/bashrc 

답변2

이 복잡한 패턴 교체에 sed를 사용하려면 다음을 수행하세요.

sed 's/${pattern}/#${pattern}/'

다음과 같은 방법으로 평가를 강제 해야 합니다 pattern.

sed 's/'${pattern}'/#'${pattern}'/'

만져서 /etc/bashrc사용하기 전에 임시 파일이 원하는 대로 작동하는지 확인하세요 sudo(또한 사용하기 전에 sudo실제로 올바른 파일을 사용하고 있는지 확인하여 가짜 파일을 사용하지 않도록 하세요).

답변3

정규식 없이 전체 줄을 바꾸려면 먼저 줄 번호를 가져올 수도 있습니다.

LNO=$(grep -FN "$pattern" </etc/bashrc | cut -d':' -f1)

해당 줄을 주석 모드와 새 줄로 바꿉니다.

[ "$LNO" ] \
&& sed -i "${LNO}s/.*/#$pattern\n$newline/" /etc/bashrc

또한 몇 달 후에는 더 명확하게 읽을 수 있습니다.

테스트 목적으로 나는 항상 sed를 임시 파일에 먼저 작성한 다음(-i 옵션 없이) 구성을 손상시키지 않도록 이름을 바꾸는 것을 좋아합니다.

[,],$ and &그러나 나는 또한 이 방법이 다음 순서로 일부 마스킹이 필요한 포함된 패턴에서는 작동하지 않는다는 것을 발견했습니다 .

pattern=${pattern//\[/\\\[}
pattern=${pattern//\]/\\]}
pattern=${pattern//\$/\\$}
pattern=${pattern//\&/\\&}
pattern=${pattern//\\/\\\\}

그 결과 다음과 같은 기능이 발생합니다.

#!/bin/bash

declare -a commentAndReplaceMask=('[' ']' '$' '&')
function commentAndReplace () {
  local p="$1"  # pattern
  local s="$p" # sed pattern
  local r="$2"  # replacement
  local f="$3"  # file

  echo args:
  echo p: $p
  echo r: $r
  echo s: $s

  s=${s//\\/\\\\}
  r=${r//\\/\\\\}
  for m in ${commentAndReplaceMask[@]}; do
    s=${s//$m/\\$m}
    r=${r//$m/\\$m}
  done

  echo prepared for sed:
  echo p: $p
  echo r: $r
  echo s: $s

  LNO=$(grep -Fn "$p" <$f | cut -d':' -f1)

  [ "$LNO" ] \
  && sed "${LNO}s/.*/# $s\n$r/" <$f >${f}.tmp

  # mv "${f}.tmp" "$f"
}

commentAndReplace "$@"

관련 정보