Многострочный поиск и замена - PullRequest
1 голос
/ 17 мая 2019

У меня есть неструктурированный файл, и я хотел бы найти и заменить шаблон строк.

  • Должен заменить строку, которая существует между строками SELECT и FROM; тот, кто находится вне этого шаблона, должен оставаться как есть.

Формат файла похож на

col4 is required to be upper so
make col4 upper
abc 12345 !$% DATA SELECT 
col1 as col1,
col2 as col2.
col3,
sch.col4 as col4,
sch.tab.col4 as col4_1,
col4,
col5 FROM sch.tab
xyz 34354 ^&* DATA SELECT
col5 as col5,
col3,
col4,
col4 as col4,
col4 FROM
blah blah blah

Я хочу заменить:

  • col4, с upper(col4) as col4,
  • sch.col4 с upper(sch.col4)
  • sch.tab.col4 с upper(sch.tab.col4)
  • col4 (если col4 находится в конце запроса выбора) с upper(col4) as col4

Файл находится на сервере Linux, и я попытался с помощью sed и awk сузить строки, содержащие col4, но не смог оттуда двигаться вперед.

Мне удалось идентифицировать один шаблон, используя ниже

awk '/SELECT/,/FROM/' test_file.txt | awk '/col4/{print $0, NR}' | awk -F AS '{print $1}' 

Найти текст между SELECT и FROM
Определите строки, которые имеют col4
напечатать первое поле

sed -n -e '/SELECT/,/FROM/p' -e 's/\(\([a-zA-Z]\{1,\}\.\)\{0,\}\)col4/upper(\0)/g' test_file.txt

и с использованием sed

Фактический:

col4 is required to be upper so
make col4 upper
abc 12345 !$% DATA SELECT
col1 as col1,
col2 as col2.
col3,
sch.col4 as col4,
sch.tab.col4 as col4_1,
col4,
col5 FROM sch.tab
xyz 34354 ^&* DATA SELECT
col5 as col5,
col3,
col4,
col4 as col4,
col4 FROM
blah blah blah

Ожидаемый результат:

col4 is required to be upper so
make col4 upper
abc 12345 !$% DATA SELECT
col1 as col1,
col2 as col2.
col3,
upper(sch.col4) as col4,
upper(sch.tab.col4) as col4_1,
upper(col4) as col4,
col5 FROM sch.tab
xyz 34354 ^& DATA SELECT
col5 as col5,
col3,
upper(col4) as col4,
upper(col4) as col4,
upper(col4) as col4 FROM
blah blah blah

Любая помощь очень ценится!

Ответы [ 4 ]

0 голосов
/ 19 мая 2019

С помощью sed:

sed '/SELECT/,/FROM/ {s/as col4 *//;s/\([A-Za-z]*\.\)\{0,\}col4/upper(&) as col4/;}' file

Пояснения:

  • s/as col4 *//: существующий as col4 удален для предотвращения дублирования после второй замены
  • \([A-Za-z]*\.\)\{0,\}col4: поиск 0 или более комбинаций букв и точек, за которыми следует col4
  • upper(&) as col4/;: заменить новым текстом (соответствующая строка вставляется с использованием &)
0 голосов
/ 17 мая 2019

Вот короткий awk-скрипт, выполняющий ваш запрос:

awk '/SELECT/,/FROM/ {$0=gensub(/^[^[:space:]]*col4/,"upper(\\0)",-1);}1' input.txt

Вывод:

abc 12345 !$% DATA SELECT
col1 as col1,
col2 as col2.
col3,
upper(sch.col4) as col4,
upper(sch.tab.col4) as col4_1,
upper(col4),
col5 FROM sch.tab
xyz 34354 ^&* DATA SELECT
col5 as col5,
col3,
upper(col4),
upper(col4) as col4,
upper(col4) FROM
blah blah blah

Объяснение:

/SELECT/,/FROM/ включительно, выбирая каждыйстрока из / SELECT / в / FROM /

$0=gensub(***) обновить текущую строку с подстановками из gensub ()

/^[^[:space:]]*col4/ поиск префикса без пробела для col4 в начале строки

upper(\\0)",-1 заменить найденное совпадение на верхнее ('найденное совпадение') только первое совпадение

1 распечатать текущую строку.1

0 голосов
/ 18 мая 2019

Ваше описание необходимых вам преобразований неполное (например, вы говорите, что хотите изменить col4, на upper(col4) as col4,, но строка 7 ожидаемого результата не отражает это), поэтому я отложил это в сторону и просто написал это, котороено вы получите желаемый результат из предоставленного вами ввода (используя GNU awk для 3-го аргумента для сопоставления ()), и, надеюсь, это именно то, что вам действительно нужно:

$ cat tst.awk
/SELECT/ { inBlock=1 }
inBlock {
    if ( match($0,/^((sch\.(tab\.)?)?col4\>)( as .*)/,a) ) {
        $0 = "upper(" a[1] ")" a[4]
    }
    else if ( match($0,/^(col4\>)(.*)/,a) ) {
        $0 = "upper(" a[1] ") as " a[1] a[2]
    }
}
/FROM/   { inBlock=0 }
{ print }

$ awk -f tst.awk file
col4 is required to be upper so
make col4 upper
abc 12345 !$% DATA SELECT
col1 as col1,
col2 as col2.
col3,
upper(sch.col4) as col4,
upper(sch.tab.col4) as col4_1,
upper(col4) as col4,
col5 FROM sch.tab
xyz 34354 ^&* DATA SELECT
col5 as col5,
col3,
upper(col4) as col4,
upper(col4) as col4,
upper(col4) as col4 FROM
blah blah blah
0 голосов
/ 17 мая 2019

Я думаю, что это, по крайней мере, 95% делает это.Пожалуйста, сообщите мне, если есть ошибка:

with open('ej.txt', 'r') as file:
    string=file.read().replace('\n',' ')


import re

matches=re.findall(r'SELECT.*?FROM',string)
replacements={"col4,":"upper(col4) as col4,",
             "sch.col4":"upper(sch.col4)",
             "sch.tab.col4":"upper(sch.tab.col4)",
             "col4 as col4,": "upper(col4) as col4,"}
new_matches=[]
for match in matches:
    for k,v in replacements.items():
        match=match.replace(k,v)
    new_matches.append(match)


for k,v in {k:v for k,v in zip(matches,new_matches)}.items() :
    string=string.replace(k,v)

string
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...