将字符串替换为非常大的文件


10

我有一连串的网址,没有分隔符,格式如下:

http://example.comhttp://example.nethttp://example.orghttp://etc...

我希望每个URL都换一行。我试图通过使用sed将“ http://”的所有实例替换为“ \ nhttp://”来做到这一点

sed 's_http://_\nhttp://_g' urls.txt

但是发生分段错误(内存冲突)。我只能推测文件的绝对大小(超过100GB)导致sed超过了一些限制。

我可以将文件分成几个较小的文件进行处理,但是“ http://”的所有实例都需要保持完整。

有一个更好的方法吗?


我认为sed不喜欢没有行尾的100GB,因为它试图读取其缓冲区中的一行。
jippie 2012年

拆分(无论切割发生在“何处”),进行处理,然后重新组装都应给出正确的结果。
enzotib 2012年

3
如果确实有一个100GB的文本文件包含一个长行,那么最好编写一个快速的C程序来完成工作。
fpmurphy

Answers:


11

这样awk您就可以避免一次阅读大量文本:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

成功可能取决于所使用的awk实现。例如gawk工作正常,但mawk崩溃。


6

这将完成工作:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

通过设置$ /,我更改了行的定义,使其以//换行符结尾。这使Perl一次读取一个URL。//除了方案之后,URL不太可能包含,但是如果包含URL ,则可以,正则表达式将阻止它添加虚假的换行符。

如果要避免在第一个URL之前添加空白行:

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

您可以尝试进行基准测试,看看是否s!http://\z!\nhttp://!更快。它们是等效的。请注意,该/g标志在替换中不是必需的,因为每条“行”只能有一个匹配项。


perl regexp引擎可以处理数千兆字节长的行吗?
Alexios

2
@Alexios,可能不是,但这不是必须的。自从我更改之后$/,一次只能处理一个URL。
cjm 2012年

啊,我明白你在那里做了什么。自90年代以来已经有一段时间了,我不得不man perlvar这样做,但是那样是有意义的。
Alexios '04

Linux允许url在路径中嵌入多个斜杠,因此,如果有任何斜杠,此代码可能会失败。测试整个字符串,http和所有字符串都不会出现此问题。
2012年

@Joe,我正在测试http:正则表达式中的部分。它将检查每一个//,但除非找到,否则不会添加换行符http://
cjm 2012年

5
  1. :用换行符更改所有出现的a 来切碎文件。
  2. 更换
    • http 在行的结尾
    • 换行符,然后在其后http:添加下一行
  3. 重复一次,以便更新偶数和奇数行

这些步骤如下所示:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. 检查是否有不以开头http://的行,打印行号。仅当a:位于URL中的某个位置(而不是。之后)时,才会发生这种情况http

    grep -nv '^http://'

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.