Предотвратите масштабирование Xrandr от расплывчаты

Это прекрасный пример того, почему sed является s tream ed itor, и никогда не заменит возможности ex для редактирования файлов на месте.

ex -c '/address  *172.29.16.103/
?{?,/}/d
x' input

Эта команда представляет собой упрощенную форму, которая не так надежна, как могла бы быть, но служит для иллюстрации.

Первая команда находит указанное регулярное выражение и перемещает курсор на эту строку.

Вторая команда состоит из двух адресов, разделенных запятой, по которым выполняется команда d elete. ? {? выполняет поиск в обратном направлении от текущей строки для открытой фигурной скобки, а /} / выполняет поиск вперед от текущей строки для закрытой фигурной скобки. Все, что находится между ними, удаляется (линейно, поэтому также удаляется начало открытой фигурной скобки).

x сохраняет изменения и выходит. И input , конечно же, имя файла.

Для введенных вами данных эта команда работает точно так, как вы хотите.


Я упомянул, что это можно значительно улучшить. Начнем с регулярного выражения. Самая очевидная особенность здесь в том, что точки - это символы подстановки; данное регулярное выражение также может соответствовать «172329-16 103». Таким образом, точки должны быть экранированы обратной косой чертой, чтобы они соответствовали только буквальным точкам.

Далее следует пробел. Я поставил два пробела, за которыми следует * (я мог бы использовать \ + , но я не знаю, требуется ли эта функция в POSIX), но что, если в файле есть вкладки? Лучшее решение - использовать [[: space:]] .(Это выглядело бы намного лучше с \ + ; если кто-нибудь обнаружит, что это POSIX, напишите комментарий.)

Наконец, что, если регулярное выражение не найдено в файле ? Что ж, тогда файл просто откроется для редактирования, и команда "search" завершится неудачно, и будет напечатано сообщение об ошибке, а остальные данные команды не будут выполнены - вы останетесь в ex редактор, чтобы вы могли вносить изменения вручную. Однако, если вы хотите автоматизировать редактирование в сценарии, вы, вероятно, захотите, чтобы редактор выходил из , если не нужно вносить никаких изменений. Ответ - использовать команду lobal g , а также использовать флаг -s для подавления любого вывода из ex :

ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d
x' input

Это не вполне эквивалент предыдущей команды; если имеется более одного блока фигурных скобок с совпадающей линией, глобальная команда удалит их все. В любом случае, вероятно, вы этого хотите.

Если вы хотите удалить только первое совпадение при выходе без изменения файла, если совпадений нет вообще, вы можете использовать команду x как часть аргумента g (для выхода из файла после выполнения первой команды удаления) и добавить q! внизу на случай, если команда g не выполняется из-за отсутствия совпадающих строк.

ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d | x
q!' input

Если честно, эти команды делают процесс намного сложнее, чем он есть на самом деле; надежность достигается за счет предельной ясности и удобочитаемости кода. Это компромисс.

Я рекомендую отредактировать несколько файлов в интерактивном режиме с помощью ex , чтобы немного почувствовать это. Таким образом вы сможете увидеть , что вы делаете. Такой сеанс редактирования в ex для интерактивного выполнения этого исправления выглядит примерно так:

$ ex input
"input" 23L, 843C
Entering Ex mode.  Type "visual" to go to Normal mode.
:/103
        host_name               ServerB_172.29.16.103
:?{?,/}/d                             # This deletes the current block

:$p                                   # Print and move to last line

:-5,.p                                # Print some more lines to check result
        notification_interval   120
        notification_period     24x7
        }



:?}?+,.d                              # Trim whitespace
        }
:x                                    # Save and exit
$ 

Спецификации POSIX для ex содержат дополнительную информацию.

0
22.10.2018, 22:40
2 ответа

[ "$OPTARG" -eq "$OPTARG" ]... не является правильным способом проверить, является ли $OPTARGчислом --он может вывести пользователю неприятную непостижимую ошибку, если это не так, или он может просто вернуть true во всех случаях (вksh)или также вернуть true для пустого$OPTARGzsh).

Кроме того, вариант, принимающий аргумент, может быть задан как -d12или -d 12, так что вслепую shift 2не подойдет. И выполнение shiftвнутри цикла может плохо взаимодействовать с getopts, который сам использует список активных аргументов.

Принимая это во внимание, вот что я предлагаю:

die(){ echo >&2 "$@"; exit 1; }
usage(){ echo >&2 "usage: $0 [-h] [-d num] files..."; exit 0; }

depth=0

while getopts :hd: opt; do
        case $opt in
        h)      usage ;;
        d)      case $OPTARG in
                ''|*[!-0-9]*|-|*?-*) die "invalid number $OPTARG" ;;
                *) depth=$OPTARG ;;
                esac
                ;;
        :)      die "argument needed to -$OPTARG" ;;
        *)      die "invalid switch -$OPTARG" ;;
        esac
done
shift "$((OPTIND - 1))"

echo depth="$depth"
echo files="$@"
5
28.01.2020, 02:16

Одинарная квадратная скобка [совместима с posix -, но ее сложнее использовать, чем [[, которую обычно можно использовать в bash. Согласно стандарту одинарной -квадратной скобки -, -eqпредназначен только для целых чисел, а не для строк. Например, следующее работает нормально:if [ "2" -eq "2" ] ; then echo foo; fi. Вы можете использовать либо двойные -квадратные -скобки, для которых -eqпринимает строки, либо использовать =и форму одинарной -квадратной скобки:

if [ "bar" = "bar" ] ; then echo foo; fi

См.https://ryanstutorials.net/bash-scripting-tutorial/bash-if-statements.phpдля получения информации о тесте POSIX if иhttp://tldp.org/LDP/abs/html/testconstructs.htmlдля получения информации о различных типах тестовых конструкций, таких как ((и [[.

0
28.01.2020, 02:16

Теги

Похожие вопросы