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 "$@"

関連情報