在一个非常大的文件中替换字符串

C S*_*yer 10 sed text-processing

我有很长的一系列没有分隔符的网址,格式如下:

http://example.comhttp://example.nethttp://example.orghttp://etc...
Run Code Online (Sandbox Code Playgroud)

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

sed 's_http://_\nhttp://_g' urls.txt
Run Code Online (Sandbox Code Playgroud)

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

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

有一个更好的方法吗?

man*_*ork 11

有了awk你能避免一次阅读大量的文字:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt
Run Code Online (Sandbox Code Playgroud)

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


cjm*_*cjm 6

这将完成这项工作:

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

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

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

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

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

  • @Alexios,可能不是,但不一定是。由于我更改了 `$/`,它一次只能处理一个 URL。 (2认同)

jip*_*pie 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:/}'
Run Code Online (Sandbox Code Playgroud)
  1. 检查是否有不以 开头http://的行,打印行号。仅当 : 在 URL 中的某个位置而不是http.

    grep -nv '^http://'