【问题标题】:Multi-line search and replace多行搜索和替换
【发布时间】:2019-05-17 15:37:53
【问题描述】:

我有一个非结构化文件,我想搜索和替换字符串模式。

  • 必须替换存在于 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.col4upper(sch.col4)
  • sch.tab.col4upper(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

非常感谢任何帮助!

【问题讨论】:

  • Python 也适合你?
  • @Juan C 嗨,是的,Python 3 也可以。
  • @oguzismail 抱歉。这是我的第一篇文章,现在编辑。

标签: python linux unix awk sed


【解决方案1】:

使用 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/;:替换为新文本(使用&插入匹配字符串)

【讨论】:

  • 谢谢@SLePort。这个解决方案对我很有效。
【解决方案2】:

我认为,至少 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

【讨论】:

  • 谢谢胡安!我将尝试使用此代码并反馈结果。
  • 它在大多数情况下都有效,但由于文件被读取为一个字符串 - 我发现很难将其恢复为原始格式。有没有办法保持格式不变并更新到位?再次感谢您的帮助!
【解决方案3】:

这是执行您的请求的简短 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 仅将 found-match 替换为-upper('found-match') 仅第一个匹配项

1 打印当前行。 1

【讨论】:

  • 谢谢!这是其中的一部分,但我想将“col4”替换为“upper(col4) as col4”,将“sch.col4”替换为“upper(sch.col4)”“sch.tab.col4”替换为“upper(sch .tab.col4)" "col4"(如果 col4 位于 select 查询的末尾),upper(col4) 为 col4
【解决方案4】:

您对所需转换的描述不完整(例如,您说您想将 col4, 更改为 upper(col4) as col4, 但预期输出的第 7 行并未反映这一点)所以我把它放在一边,只是写了这个但会从您提供的输入中产生您想要的输出(使用 GNU awk 将第三个 arg 用于 match()),希望这是您真正想要的:

$ 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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-01-31
  • 2018-05-16
  • 2015-08-24
  • 2021-02-18
  • 2013-10-18
  • 2015-02-20
  • 1970-01-01
  • 2010-09-21
相关资源
最近更新 更多