提取.txt文件中两个关键字之间的所有单词

时间:2019-12-11 16:57:59

标签: python regex text

我想提取.txt文件中特定关键字内的所有单词。对于关键字,有一个起始关键字PROC SQL;(我需要区分大小写),结束关键字可以是RUN;quit;QUIT;。这是我的示例.txt file

到目前为止,这是我的代码:

with open('lan sample text file1.txt') as file:
    text = file.read()
    regex = re.compile(r'(PROC SQL;|proc sql;(.*?)RUN;|quit;|QUIT;)')
    k = regex.findall(text)
    print(k)

输出:

[('quit;', ''), ('quit;', ''), ('PROC SQL;', '')]

但是,我的预期输出是使单词介于两者之间,并包含关键字:

proc sql; ("TRUuuuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 );

1)

jjjjjj;

  select xx("xE'", PUT(xx.xxxx.),"'") jdfjhf:jhfjj from xxxx_x_xx_L ;
quit; 

PROC SQL; ("CUuuiiiiuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 );

2)(

RUN;

任何建议或其他解决方法将不胜感激!

实施用户@Finefoot的代码后的输出: enter image description here

但是,有没有一种方法可以将这些行分隔成类似下面的样子?:

enter image description here

4 个答案:

答案 0 :(得分:2)

如果不想使用正则表达式的解决方案:

=
MID(
    Fields!sql.Value,
    INSTR(Fields!sql.Value, "WHERE ", Compare:= Comparemethod.Text) + 6
    )

对您有帮助吗?

答案 1 :(得分:1)

我认为您的模式(PROC SQL;|proc sql;(.*?)RUN;|quit;|QUIT;)是一个错字,因为您在)之后和proc sql;之前以及右括号{之前都缺少右括号(.*?) {1}}之后。但是,还不止这些,修正错字仍然无法达到预期的效果。

看看re的Python文档:

  

((点)。在默认模式下,它匹配换行符以外的任何字符。如果指定了.标志,则它与包括换行符的任何字符匹配。

由于您的输入中确实包含您希望DOTALL匹配的换行符,因此您需要使用.标志。当我们讨论标志时:如果您确实不关心关键字的区分大小写,则可能还想使用re.DOTALL标志。

此外,我想您不想在结果中使用类似re.IGNORECASE之类的关键字,因此您可以使用PROC SQL;,这是常规括号的非捕获版本。

最终的正则表达式模式:

(?:...)

更新

在上面Jupyter单元中的更新代码中,re.findall(r"(?:PROC SQL;)(.*?)(?:RUN;|QUIT;)", text, flags=re.IGNORECASE|re.DOTALL) 的结果保存为变量re.findall。这是与模式匹配的字符串列表。如果调用regex,则将打印列表(将使用print(regex)显示其元素,字符串)。如果您不想使用\n,则可以打印元素(字符串本身):\n不过,两个元素之间的默认分隔符将是一个简单的空格字符,因此您可能需要设置print(*regex)到多个换行符sepprint(*regex, sep="\n"*5)的分隔行,如-----之类的东西。但这是您必须决定哪种方式最适合您呈现结果的事情。

此外,如果该模式看起来还不太混乱,则可能要使用“内联修饰符”而不是print(*regex, sep="\n"+"-"*44+"\n")参数。 flags用于不区分大小写的匹配,(?i:...)代替(?s:...)标志:

DOTALL

答案 2 :(得分:1)

这对我有用:

re.findall(r"(?i:PROC SQL;)((?s:.*?))(?i:RUN;|QUIT;)", text)

这是您可以接受的解决方案吗?

答案 3 :(得分:1)

您可以通过匹配关键字并匹配所有以colNumbers = [] def letterTonumber(col): A = ord('A') tempSum = sum(ord(l) - A + 1 for l in col if 'A' <= l <='Z') return(tempSum) def colParse(colNumbers, cols): for c in cols: if len(c) == 2: x=26*letterTonumber(c[0]) y=letterTonumber(c[1]) n=(x+y)-1 else: n = letterTonumber(c)-1 colNumbers.append(n) cols = ['A','Z','AA','BB'] colParse(colNumbers, cols) print(colNumbers) >>> 0,25,26,53 quit开头的行来更有效地进行匹配,以防止由RUN引起的不必要的回溯

如果要在匹配项中包含关键字,则可以省略捕获组。

您可以使用.*?标志获得不区分大小写的匹配,并使用re.IGNORECASE,因为该模式包含一个断言字符串开头的锚点。

re.MULTILINE
  • ^PROC SQL;.*\n(?:(?!RUN;|QUIT;).*\n)*(?:RUN|QUIT); 行首
  • ^字面上匹配
  • PROC SQL;匹配0+次除换行符以外的任何字符,然后匹配换行符(或使用.*\n
  • \r?\n非捕获组
    • (?:断言直接在右边的不是(?!RUN;|QUIT;)RUN;
    • QUIT;匹配0+次除换行符以外的所有字符,然后匹配换行符
  • .*\n关闭组并重复0次以上
  • )*匹配(?:RUN|QUIT);RUN;

Regex demo | Python demo

例如

QUIT;