У меня есть файл (/usr/test.log) с кучей строк, в форме

[enable/disable] [name] [stuff]

Например:

enable telnet max_pkt 0 max_payload 0 min_payload 1 disable_function 0 inherit_max_packets 0
enable telnets max_pkt 0 max_payload 0 min_payload 0 disable_function 0 inherit_max_packets 0
disable teredo max_pkt 0 max_payload 0 min_payload 40 disable_function 0 inherit_max_packets 0

При наличии имени и статуса ("включить" или "отключить"), что такое команда sed чтобы заменить строку, содержащую данное имя, данным статусом? Например, учитывая "telnet" и "отключить", это изменило бы первую строку выше на

disable telnet max_pkt 0 max_payload 0 min_payload 1 disable_function 0 inherit_max_packets 0

Если есть более простые способы программного выполнения этих операций из командной строки без использования sed , это тоже хорошо.

3 ответа3

1

Если вы знаете, что вы хотите заменить это просто

sed -i 's/^enable telnet /disable telnet /g' filename 

Пока полезная нагрузка находится между [enable/disable] [name], это должно быть хорошо. Символ «^» должен соответствовать началу строки.

Если вы хотите обменять значение независимо от текущего состояния, вы можете использовать ветвление в sed

sed 's/^enable telnet /disable telnet /g 
     b end                                    #go to end if first rule has matched
     s/^disable telnet /enable telnet /g
     :end'  filename
1

Это делает это. Досадно, | , ( , и ) нужно убежать.

sed -i 's/^\(enable\|disable\) telnet/disable telnet/g' /usr/test.log
1

С AWK:

tmp=$(mktemp); awk '$2=="telnet" {$1="disable"} {print}' test.log > $tmp && mv $tmp test.log

Выше будет писать disable в строке telnet .

Сценарии это:

#!/bin/sh
file=/path/to/test.log

usage() {
    cat <<-USAGE
    Enable/disable services in $file

    usage: ${0##*/} SERVICE [enable|disable]

    positional arguments:
      SERVICE   service name
    USAGE
    exitstatus=${1:-1}
    exit $exitstatus
}

error() {
    printf '%s: error: %s\n' "${0##*/}" "$1" 1>&2
    [ -z "$2" ] || exit $2
}

success() {
    printf '%s: Service `%s` %sd\n' "${0##*/}" "$service" "$status"
}

[ -f "$file" ] || error 'File not found.' 2

tmp=$(mktemp)

[ $# -eq 0 ] && usage

if [ $# -ne 2 ] || ( [ "$2" != "enable" ] && [ "$2" != "disable" ] ); then
    error 'Argument error.'
    usage 3
fi

service=$1
status=$2

awk -v status="$status" -v service="$service" -v ok=99 \
    '$2==service {$1=status; ok=0} {print} END{exit ok}' "$file" > $tmp
awkexit=$?
case $awkexit in
    0 )  mv $tmp "$file" && success;;
    99)  error 'Service not found.' 4;;
    * )  error 'Unkown error. Status change failed.' 5;;
esac

Измените file на реальный путь к рассматриваемому файлу. Сохраните скрипт как, например, myservice , сделайте его исполняемым, поместите его в PATH , и затем он может быть выполнен следующим образом:

$ myservice telnet disable
myservice: Service `telnet` disabled.

Сценарий сообщит вам, было ли изменение статуса успешным или не существует ли служба в данном файле. Я "злоупотребляю" кодом выхода AWK, чтобы проверить статус изменений.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .