#sed
#sed
Вопрос:
Я создал небольшой образец того, с чем я работаю на данный момент. Я пытаюсь правильно указать значения по УМОЛЧАНИЮ, в частности, DEFAULT ONE
значение # 2 должно быть указано как DEFAULT 'ONE'
:
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT ONE AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '' FIRST;
В настоящее время я использую следующую строку против приведенных выше строк, чтобы исправить строку # 2:
sed "s/DEFAULT ([a-zA-Z0-9_.]*)/DEFAULT '1'/g"
Это результат, который я получаю:
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT 'NULL') ENGINE=InnoDB DEFAULT 'CHARSET'=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT 'ONE' AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '''' FIRST;
Как вы можете видеть, это исправляет строку # 2, но в # 1 и # 3 теперь есть проблемы.
#1 DEFAULT 'NULL' (should remain DEFAULT NULL)
#1 DEFAULT 'CHARSET' (should remain DEFAULT CHARSET)
#2 DEFAULT 'ONE' (GOOD!)
#3 DEFAULT '''' (should remain DEFAULT '')
Есть ли способ настроить sed для игнорирования определенных шаблонов, таких как DEFAULT NULL
или DEFAULT CHARSET
или DEFAULT ''
?
sed "s/DEFAULT (not followed by NULL|CHARSET|'')([a-zA-Z0-9_.]*)/DEFAULT '1'/g"
Или, возможно, есть подход получше?
Спасибо!
Ответ №1:
Если Perl
это ваш вариант, пожалуйста, попробуйте:
perl -pe "s/(DEFAULT) (?!(NULL|CHARSET|''))([a-zA-Z0-9_] )/1 '3'/g" file
Вывод:
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT 'ONE' AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '' FIRST;
Комментарии:
1. Это также отлично работает, хотя в ответе @John1024 используется sed. Хотя мне это действительно нравится. Это кажется очень чистым и легко управляемым.. Я почти уверен, что также добавлю больше слов в список в ближайшем будущем (например, CURRENT_TIMESTAMP). Итак, большое вам спасибо за то, что поделились этим ответом!
Ответ №2:
Попробуйте:
sed -E "s/DEFAULT (NULL|CHARSET)/DEFAULT_1/g; s/DEFAULT ([[:alnum:]_.] )/DEFAULT '1'/g; s/DEFAULT_(NULL|CHARSET)/DEFAULT 1/g" file
Это выполняется в три этапа:
-
s/DEFAULT (NULL|CHARSET)/DEFAULT_1/g
Это скрывает значения по УМОЛЧАНИЮ, которые вы не хотите изменять.
-
s/DEFAULT ([[:alnum:]_.] )/DEFAULT '1'/g
Это изменяет значения, которые вы действительно хотите изменить.
Обратите внимание, что я изменил
*
наЯ также изменил
[a-zA-Z0-9]
на[:alnum:]
, чтобы регулярное выражение соответствовало всем буквенно-цифровым символам безопасным для юникода способом. (Если это не то, что вы хотели, просто измените эту часть обратно.) -
s/DEFAULT_(NULL|CHARSET)/DEFAULT 1/g
Это вернет те, которые вы не хотите изменять.
Этот подход предполагает, что ни DEFAULT_NULL
ни DEFAULT_CHARSET
не отображаются в вашем фактическом вводе. Основываясь на том, что вы показали до сих пор, это выглядит как безопасное предположение.
Пример
С помощью вашего входного файла:
$ cat file
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT ONE AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '' FIRST;
Наша команда производит:
$ sed -E "s/DEFAULT (NULL|CHARSET)/n1/g; s/DEFAULT ([[:alnum:]_.] )/DEFAULT '1'/g; s/n(NULL|CHARSET)/DEFAULT 1/g" file
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT 'ONE' AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '' FIRST;
Комментарии:
1. Это работает отлично. Нравится разбивка объяснений. Большое вам спасибо! Очень полезно.
2. Что, если
DEFAULT_FOO
во входных данных уже существует строка? Если вы используетеn
вместо_
для создания временной строки, то вы знаете, что она еще не существует во входных данных, разделенныхn
, как это читается sed по умолчанию.
Ответ №3:
С помощью GNU awk для RS с несколькими символами:
awk -v RS='DEFAULT \w ' -v ORS= '
RT { split(RT,rt); if (rt[2] !~ /^(NULL|CHARSET)$/) RT=rt[1]" 47"rt[2]"47" }
{ print $0 RT }
' file
#1 CREATE TABLE `table` (`column` int(10) unsigned DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
#2 ALTER TABLE `table` MODIFY COLUMN `column2` enum('ONE','TWO') NOT NULL DEFAULT 'ONE' AFTER `column1`;
#3 ALTER TABLE `table` MODIFY COLUMN `column` varchar(64) NOT NULL DEFAULT '' FIRST;