У меня есть неструктурированный файл, и я хотел бы найти и заменить шаблон строк.
Формат файла такой
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
Любая помощь высоко ценится!!
@Juan C Привет, да, Python 3 тоже работает.
@oguzismail Извинения. Это мой первый пост, отредактированный сейчас.
Я думаю, это, по крайней мере, 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
Спасибо Хуан! Я попробую с этим кодом и отпишусь о результатах.
По большей части это сработало, но поскольку файл читался как одна строка, мне трудно вернуть его в исходный формат. Есть ли способ сохранить формат как есть и обновить на месте? Еще раз спасибо за помощь!
Вот короткий 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
Спасибо! Это делает часть этого, но я хочу заменить «col4» на «upper (col4) as col4», «sch.col4» на «upper (sch.col4)», «sch.tab.col4» на «upper (sch .tab.col4)" "col4"(если col4 находится в конце запроса выбора) с upper(col4) как col4
Ваше описание необходимых вам преобразований является неполным (например, вы говорите, что хотите изменить col4,
на upper(col4) as col4,
, но строка 7 ожидаемого вывода не отражает этого), поэтому я отложил это и просто написал это, но оно даст желаемый результат из предоставленного вами ввода (используя GNU awk для третьего аргумента для соответствия()), и, надеюсь, это то, что вы действительно хотите:
$ 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
Спасибо Эд! Это решение помогло мне.
Пожалуйста. См. stackoverflow.com/help/someone-answers, чтобы узнать, что делать дальше.
С СЭД:
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/;
: заменить новым текстом (соответствующая строка вставляется с помощью &
)Спасибо @SLePort. Это решение отлично сработало для меня.
Python также работает для вас?