使用VI替换第一个出现/实例非常简单。
:%s/search/replace/args
但是,这是我的数据集.csv格式/文件:
"192.168.2.1","www.google.com","2009/01/11_10:00"," What a great website"
"192.168.2.2/driving/is/fun","-","2009/03/22_00:00","Driving website"
"192.168.2.4/boating/is/crazy","-","2009/03/22_00:00","Boating Website"
"192.168.2.5","www.cars.com","2009/04/27_00:00","What a good car website"
所以,你会注意到第一行有4列,这是.csv格式的理想行。
但是,在第二行中,有4列,但第一列只接受ip地址而已,只有192.168.2.2/driving/is/fun必须删除或用“,”.csv分隔符分隔
在vi中,我能够使用以下内容:
:/^"\d\{,3}\.\d\{,3}\.\d\{,3}\.\d\{,3}\//s/\//","/
执行以下操作:
/ ^“\ d {,3}。\ d {,3}。\ d {,3}。\ d {,3} / - 设置锚点以在第一个IP处开始搜索正斜杠/。例如,第2行:“192.168.2.2 /
/ s ///“,”/ - 替换IP地址末尾的/并用.csv分隔符替换它“,”
这在VI / VIM中效果很好,一次取代我需要的一行。但是,数据集要大得多,并且使用以下vi搜索和替换手动操作非常耗时。我希望编写脚本或找到替代解决方案,因为VI / VIM一次只能执行一行,以下内容:s / search / replace / g替换每行/更改日期列的行。
显然,我尝试了以下方法:
在替换开头的内部添加整个文件的%,如下所示:
:/^"\d\{,3}\.\d\{,3}\.\d\{,3}\.\d\{,3}\//%s/\//","/
突出显示我需要修改的每个条目,但错误输出:
E492: Not an editor command: /^"\d\{,3}\.\d\{,3}\.\d\{,3}\.\d\{,3}\//%s/\//
这相当令人困惑。
我最终想用sed / perl编写一次编辑整个文件的脚本。
所以..
“192.168.2.2/ - >”192.168.2.2“,”
每一行都是第一次出现。
任何帮助将不胜感激..
谢谢!
答案 0 :(得分:4)
在vi / vim中,您可以指定要替换的搜索范围。在这种情况下,您希望在所有行中替换:%s
:
:%s/search/replace/g
您还可以指定:
:2,5s/search/replace/g Replace on lines 2-5
:.,$s/search/replace/g Replace from current line (.) to last line ($)
:.,+3s/search/replace/g Replace on the current line (.) and the two next lines (+3)
:g/^asd/s/search/replace/g Replace on lines starting with 'asd'.
然后,您可以将其与更简单的模式结合使用,以在整个文件中进行所需的替换:
:%s/^\("[^/"]*\)[^"]*"/\1"/
这将删除CSV中第一个条目的IP地址后的所有内容。
:%s/^\("[^/"]*\)\/\([^"]*\)"/\1","\2/
这会将第一个条目拆分为IP地址和其余部分,但这只会在IP之后有斜杠的行中完成。 你要做的是找到模式,转到那条线然后替换。在这种情况下添加'%'会使命令无效。
答案 1 :(得分:3)
在ViM中,尝试:
:%s/^\("\d\{,3}\.\d\{,3}\.\d\{,3}\.\d\{,3}\)\(\/[^"]\)/\1","\2
也就是说,代替搜索/替代,我使用全局(%
是1,$
的快捷方式,即从第一行到最后一行)替换。我将您的搜索模式移动到替换模式中,并在单独的组中捕获IP地址和路径。然后将它们替换回去,在它们之间挤压","
。
答案 2 :(得分:2)
你可以用更简单的模式做你想做的事:
s/^\("[^/"]*\)[^"]*"/\1"/
这是:匹配行首,开始匹配组:匹配"
,匹配任意数量不是斜杠且不是"
的字符,关闭匹配组,匹配任意数量的字符不是"
,并且匹配"
。替换为匹配组内容加上"
。
上述模式应该非常简单。这是一个Python示例。
#!/usr/bin/env python
import re
import sys
if len(sys.argv) != 3:
print("Usage: log_file_cleaner <input_file> <output_file>")
sys.exit(1)
pat = re.compile(r'^("[^/"]*)[^"]*"')
with open(sys.argv[1]) as in_f, open(sys.argv[2], "w") as out_f:
for line in in_f:
line = re.sub(pat, r'\1"', line)
out_f.write(line)
注意:您需要最新版本的Python来执行一次with
来执行两次open()
次调用。如果你被困在Cygwin上,你可以将上面的内容编辑为两个嵌套with
语句,每个语句都进行一次open()
调用。