2016-08-24 86 views
2

我在寻找是否有自动执行此过程的方法。基本上我有每天需要下载的30万行数据。有几行需要在可以上传到SQL之前进行编辑。查找并编辑文本文件

Jordan || Michael | 23 | Bulls | Chicago 

Bryant | Kobe ||| 8 || LA 

我想完成的是每行只有4个竖条。通常情况下,我会搜索一个关键字,然后手动编辑然后保存。这两个是我的数据中唯一的异常情况。

  1. 找到“Jordan”,然后删除多余的1个竖条“|”紧随其后。
  2. 我需要找到“神户”,然后删除两个多余的垂直条“|”紧随其后。

正确的格式如下 -

Jordan | Michael | 23 | Bulls | Chicago 

Bryant | Kobe | 8 || LA 

不知道这是否可以在VBScript或Python来完成。 任何帮助,将不胜感激。谢谢!

+0

为什么8之后仍然有两个'|'? –

+0

嗨。在上面的例子中,每行总是应该有四个垂直条来分隔每个字段。有些情况下字段可以是空白的,就像上面的例子。 –

回答

2

Python或vbscript可以使用,但它们过于简单。尝试sed

$ sed -E 's/(Jordan *)\|/\1/g; s/(Kobe *)\| *\|/\1/g' file 
Jordan | Michael | 23 | Bulls | Chicago 
Bryant | Kobe | 8 || LA 

要保存到一个新文件:

sed -E 's/(Jordan *)\|/\1/g; s/(Kobe *)\| *\|/\1/g' file >newfile 

或者,改变就地现有文件:

sed -Ei.bak 's/(Jordan *)\|/\1/g; s/(Kobe *)\| *\|/\1/g' file 

它是如何工作

的sed逐行读取和处理文件。在我们的例子中,我们只需要具有s/old/new/g格式的替换命令,其中old是一个正则表达式,如果找到它,则替换为new。命令结尾的可选g告诉sed执行替换命令“全局”,这意味着不仅仅是一次,而是多次出现在行上。

  • s/(Jordan *)\|/\1/g

    这告诉sed寻找乔丹后跟零个或多个空格,然后竖线和删除竖线。

    更详细地说,(Jordan *)中的parens告诉sed保存字符串Jordan,后跟零个或多个空格作为一个组。在替换方面,我们将该组引用为\1

  • s/(Kobe *)\| *\|/\1/g

    同样,这告诉sed找科比后跟零个或多个空格,然后竖线和删除竖线。

使用Python

使用与上述相同的逻辑,这里是一个Python程序:

$ cat kobe.py 
import re 
with open('file') as f: 
    for line in f: 
     line = re.sub(r'(Jordan *)\|', r'\1', line) 
     line = re.sub(r'(Kobe *)\| *\|', r'\1', line) 
     print(line.rstrip('\n')) 
$ python kobe.py 
Jordan | Michael | 23 | Bulls | Chicago 
Bryant | Kobe | 8 || LA 

要的是保存到一个新的文件:

python kobe.py >newfile 
+0

嗨,哇!只需几行代码。我对sed不熟悉,是否可以在Windows中运行?谢谢! –

+0

@JamesVici在Windows上安装'sed'有很多种方法。我知道它是例如Cygwin,GNUWin32和msys包的一部分。或者,我只是用Python代码更新了答案。 – John1024

+0

你们是这个名字的钥匙,记得他有30万行的名字。 –

1

我写的Python 3.5中的代码片段如下。

# -*- coding: utf-8 -*- 

rows = ["Jordan||Michael|23|Bulls|Chicago", 
     "Bryant|Kobe|||8||LA"] 

keywords = ["Jordan", "Kobe"]   

def get_keyword(row, keywords): 
    for word in keywords: 
     if word in row: 
      return word 
    else: 
     return None    

for line in rows: 
    num_bars = line.count('|') 
    num_bars_del = num_bars - 4 # Number of bars to be deleted 
    kw = get_keyword(line, keywords) 
    if kw: # this line contains a keyword 
     # Split the line by the keyword 
     first, second = line.split(kw) 
     second = second.lstrip() 
     result = "%s%s%s"%(first, kw, second[num_bars_del:]) 
     print(result)