在bash脚本中使用sed进行搜索和修改

时间:2015-06-03 04:00:35

标签: bash sed

我正在尝试使用脚本

编辑postgres配置文件

我想搜索

listen_addresses = '*' 已经存在与否如果已经存在,则不执行任何操作,如果不存在确切的字符串,请使用以下规则

添加条目

如果有listen_addresses的任何配置行但是存在'*'的任何其他值,那么我需要用注释评论该行  Commented out on DD-MM-YYYY by XYZ 然后添加一个新行 listen_addresses = '*'   然后是评论

Added on DD-MM-YYYY by XYZ

我尝试的是这样的事情:

sed -i 's/^#?listen_addresses .*/listen_addresses = '*'/'  /etc/postgresql/9.3/main/postgresql.conf

但这无助于添加评论,只会插入 由于缺少转义字符而导致listen_addresses = *

我无法弄清楚如何完成这项改变。

2 个答案:

答案 0 :(得分:3)

  • 如果它不存在,你想从评论开始吗?听起来很矛盾,但是呃。

  • 任何以listen_addresses开头并带有任何其他值的行 - 匹配" [this] 后面没有 [that]"需要消极的前瞻,sed正则表达不支持。

  • sed逐行处理,这使搜索整个文件变得困难,然后决定是否进行更改。

如果你这样做会更容易:

a)注释每个 listen_address =行,无论它是否正确,然后始终在文件的末尾添加一个新行:

sed -i "s/^\(listen_addresses .*\)/# Commented out by Name YYYY-MM-DD \1/" postgresql.conf
echo "listen_addresses = '*'" >> postgresql.conf

如果你经常运行这个脚本,那会很烦人,因为文件会不断增长和发展。

b)使用sed以外的工具。但是你还没有说你还有其他工具可用。 Grep会让它更容易,Perl更容易。但坚持使用sed(和bash),上面的变化如何:

# Comment out every listen_address line:
sed -i "s/^\(listen_addresses .*\)/#\1 Commented out by Name YYYY-MM-DD/" postgresql.conf

# Try to uncomment a correct one:
sed -i "s/^#\(listen_addresses = '\*'\).*/\1/" postgresql.conf

# Check if the correct one exists, and if it doesn't, add it:
if ! sed -n -e "/^listen_addresses = '\*'/!ba;Q0;:a;\$Q1" postgresql.conf ; then
  echo "listen_addresses = '*'" >> postgresql.conf
fi

修改

好的,受限制的sed只是很有趣,但这是更直接的逻辑,并在评论后添加新行。

#!/bin/env bash

if grep -q "^listen_addresses = '\*'" postgresql.conf ; then
    echo "Correct listen_addresses found, doing nothing"
    exit
fi

if ! grep -q "^listen_addresses =.*" postgresql.conf ; then
    echo "No listen_addresses found, adding one at the end"
    echo "listen_addresses = '*'" >> postgresql.conf
    exit
fi

if grep -q "^listen_addresses =.*" postgresql.conf ; then
    echo "Wrong listen_addresses found, commenting them out"
    sed -i "s/^\(listen_addresses.*\)/#\1 Commented out by Name YYYY-MM-DD/" postgresql.conf

    echo "Adding correct one"
    sed -i "/^#listen_addresses/a listen_addresses = '\*'" postgresql.conf
fi

答案 1 :(得分:2)

在shell中,您不能在单引号中嵌套单引号。在sed。中使用双引号来使用shell变量。

试试这个sed:

comment="commented on $(date)"
sed -i "s~^#?listen_addresses .*~listen_addresses = '*'\n$comment~" /etc/postgresql/9.3/main/postgresql.conf