sed:多行替换配置块

use*_*738 5 sed shell-script text-processing

我有一些基本看起来像的配置文件

(...content...)
# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY
(... more content ...)
# END DYNAMIC BLOCK
(... even more content ...)
Run Code Online (Sandbox Code Playgroud)

现在,在 bash 中使用CONTENT=`wget -O - http://$SERVER/get_config.php`,我可以替换动态块。

我现在如何进行替换以及如何让脚本在文件末尾插入块(如果它不存在)?

Gil*_*il' 7

如果你想使用 sed,你可以从命名管道中读取。请注意,此代码不会尝试处理错误。如果动态块头出现不止一次,脚本将被阻止。

CONTENT_URL="http://$SERVER/get_config.php"
tmp=$(mktemp -d)
(
  cd "$tmp"
  mkfifo dynamic_seen dynamic_content
  : >dynamic_seen & seen_pid=$!
  wget -O dynamic_content "$CONTENT_URL" & wget_pid=$!
  sed -e '/^# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY$/ p' \
      -e '/^# END DYNAMIC BLOCK$/ {'
          -e p -e 'r dynamic_seen' -e 'r dynamic_content' -e '}' \
      -e '/^# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY$/, /^# END DYNAMIC BLOCK$/ d'
  if ! kill $dynamic_seen 2>/dev/null; then
    # The pipe hasn't been read, so there was no dynamic block. Add one.
    echo "# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY"
    cat dynamic_pipe
    echo "# END DYNAMIC BLOCK - DO NOT EDIT MANUALLY"
  fi
)
rm -rf "$tmp"
Run Code Online (Sandbox Code Playgroud)

但我会选择 awk。

export CONTENT_URL="http://$SERVER/get_config.php"
awk '
    $0 == "# END DYNAMIC BLOCK - DO NOT EDIT MANUALLY" {skip=0; system("wget \"$CONTENT_URL\""); substituted=1}
    !skip {print}
    $0 == "# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY" {skip=1}
    END {
         if (!substituted) {
            print "# BEGIN DYNAMIC BLOCK - DO NOT EDIT MANUALLY";
            system("wget \"$CONTENT_URL\"");
            print "# END DYNAMIC BLOCK - DO NOT EDIT MANUALLY";
        }
    }
'
Run Code Online (Sandbox Code Playgroud)

  • +1 用于 awk 解决方案。风格加分。非常紧凑、干净和可读的解决方案。直接进入我的备忘单:) (2认同)