【问题标题】:replace \n\t pattern in a file替换文件中的 \n\t 模式
【发布时间】:2015-07-31 17:35:46
【问题描述】:

好的,我有一个用竖线分隔的记录集

我正在检查每行的分隔符数量,因为它们已经开始包括 |在数据中(我们不能更改传入的文件)

在使用出色的 awk 将不良记录解析为不良文件进行处理时,我们发现某些数据具有换行符 (\n)(后跟制表符 (\t))

我试过 sed 用 \t 替换 \n\t 但它总是用 \r\n 更改 \n\t 或替换所有 \n (文件是 \r\n 用于行结束)

是的,回答下面的一些问题......

文件可以大到 200+ mb

数据中的换行是虚假的(不是每一行..但足以令人痛苦)

我试过了

sed ':a;N;$!ba;s/\n\t/\t/g' Clicks.txt >test2.txt

sed 's/\n\t/\t/g' Clicks.txt >test1.txt

样本记录

12345|876|测试数据\n
\t\t\t\t一些文字|6209\r\n

想要 12345|876|测试数据\t\t\t\t一些文本|6209\r\n

请帮忙!!!

NOTE 必须在 KSH 中(具体来说是 MKS KSH)

我不在乎它是否是 sed.. 只需要更正问题...

下面的几个解决方案在小数据上醒来或完成部分工作......

顺便说一句,我已经开始尝试删除所有换行符,然后用回车换行符替换 caraige return .. 但也不能完全让它工作

我尝试过 TR,但由于它是单个字符,它只解决了部分问题

tr -d '\n' test.txt 给我一个 \r 结尾的文件....

需要得到它到\r\n(并且这个系统上不存在dos2unix或unix2dos)

【问题讨论】:

  • 在 cmdline 上,输入时使用 ctrl-v enter 而不是 \n
  • 这也可以在脚本中使用吗?
  • 这是\n 虚假的(在正常行数据中)吗?或者这是 \r\t\n 作为行尾? sed 是基于行的,因此处理\n 总是很困难。
  • 应该。如果有帮助,您也可以尝试todos 命令将文件更改为 unix 样式。
  • sed 不适合做任何跨越多行的事情。 1970 年代中期,当 awk 被发明时,所有试图这样做的构造都已过时。编辑您的问题以显示产生多于一行输出的输入(如果存在这样的事情),并说明您的示例输入/输出中的 \ns 和 \ts 是否是文字制表符和换行符。看起来您真正想要的是删除不是紧跟在 \r 之后的每个 \n,但 idk...

标签: regex awk sed ksh


【解决方案1】:

目前尚不清楚您要做什么,但鉴于此输入文件:

$ cat -v file                                                
12345|876|testdata
        some text|6209^M

这是你想要做的:

$ gawk 'BEGIN{RS=ORS="\r\n"} {gsub(/\n/,"")} 1' file | cat -v
12345|876|testdata      some text|6209^M

以上使用 GNU awk 进行多字符 RS。或者使用任何 awk:

$ awk '{rec = rec $0} /\r$/{print rec; rec=""}' file | cat -v
12345|876|testdata      some text|6209^M

上面的cat -vs 只是用来显示\rs (^Ms) 的位置。

【讨论】:

  • 如果我用你正在替换回车的 \r 阅读此内容...我需要“额外”换行符消失..我需要回车换行。
  • 您没有正确阅读。无需猜测脚本在做什么 - 只需查看我发布的输入/输出即可。我什至将它传送到cat -v,这样您就可以清楚地将\rs 视为^Ms。有什么不清楚的地方吗?亲自尝试一下,如果它在某些方面表现不佳,请告诉我。
  • awk 命令给出以下错误:awk: line 0 (NR=82549): enough memory for string storage
  • 我喜欢理解和学习......所以我的问题......我可能想将它用于其他目的......所以请原谅我的问题
  • 提问完全没问题。我的回答中有 2 个 awk 命令。哪个给出了错误信息?您使用的是哪个版本的 awk?我的猜测是您正在运行第二个 awk 命令,并且您的输入文件中实际上没有任何 \rs ,这就是为什么该命令只是将行作为单个字符串保持累积,直到内存不足。当您在输入文件上运行cat -v 时,您是否看到任何^Ms?也有可能您使用的 awk 不能正确翻译 \r - 尝试使用文字 control-M 代替 \r
【解决方案2】:

请注意,以下解决方案将输入文件作为一个整体读入内存,这不适用于大文件。
一般来说Ed Morton's awk solution比较好。

这是一个符合 POSIX 的 sed 解决方案

tab=$(printf '\t')
sed -e ':a' -e '$!{N;ba' -e '}' -e "s/\n${tab}/${tab}/g" Clicks.txt

使此 POSIX 兼容的关键:

  • POSIX sed 不能将 \t 识别为转义序列,因此必须在脚本中使用 literal 选项卡 - 通过变量 $tab 创建,使用 tab=$(printf '\t') 创建。
  • POSIX sed - 或至少 BSD sed - 需要 标签名称(例如 :a 和上面 ba 中的 a) - 无论是隐含的还是显式的 - 到使用实际的换行符终止,或者,通过在下一个 -e 选项中继续脚本来隐式终止,这是此处选择的方法。
  • -e ':a' -e '$!{N;ba' -e '}' 是一个成熟的 Sed 习惯用法,它只是简单地“啜饮”整个输入文件(使用循环首先将 all 行读取到其缓冲区中)。这是启用后续字符串替换输入行的先决条件。
  • 注意最后一个-e 选项的选项参数是一个双引号 字符串,以便对shell 变量$tab 的引用扩展为实际在 Sed 看到它们之前的选项卡。相比之下,\n 是 POSIX sed 本身识别的 one 转义序列(在 regex 部分,而不是 replacement-string 部分) .

或者,如果您的 shell 支持 ANSI C-quoted strings ($'...'),您可以直接使用它们来生成所需的控制字符:

sed -e ':a' -e '$!{N;ba' -e '}' -e $'s/\\n\t/\\t/g' Clicks.txt

注意最后一个 -e 选项的选项参数如何是 ANSI C 引用的字符串,以及 literal \n(这是 的一个转义序列 被 POSIX Sed 识别)必须表示为 \\n。相比之下,$'...' 在 Sed 看到之前将 \t 扩展为 实际 选项卡。

【讨论】:

  • 请注意,OP 使用的是 MKS。 ANSI字符串和here-string都可以在ksh93u+中使用,不知道还有哪些版本支持。
  • @MarkReed:谢谢;如您所知,我已经修改了我的答案以提供符合 POSIX 的解决方案;但是,mkssoftware.com/docs/man1/sh.1.asp 告诉我,即使是 MKS Ksh 也支持 ANSI C 引用的字符串 ($'...');相比之下,here-strings (<<<...) 似乎不受支持。
  • sed ':a^J$!{N;ba^J};s/\n\t/ /g' clicks.txt 其中^J 是通过 CTRL+V+J 输入的换行符,大空格可以是真正的制表符或 `` 后跟 CTRL+V+I。
  • @NeronLeVelu:是的,使用实际的换行符来终止标签名称始终是一种选择,但目标是保持解决方案单行,因此有多个 -e 选项。使用 actual 制表符对我来说太微妙了——从视觉上看,您正在处理制表符(而不是空格),并且善意的编辑器可以为您将它们转换为空格。
  • 我明白了;什么错误,你在什么平台上,你使用什么 Sed 实现和版本?
【解决方案3】:

如果输入文件很小(因此您不介意处理两次),您可以使用

cat input.txt | tr -d "\n" | sed 's/\r/\r\n/g'

编辑: 正如我现在应该知道的那样,您可以避免在任何地方使用 cat 。 我已经在 SO for UUOC 中查看了我的旧答案,并仔细检查了 tr 用法中可能的文件名。正如 Ed 在他的评论中指出的那样,cat 也可以在这里避免:

上面的命令可以改进

tr -d "\n" < input.txt | sed 's/\r/\r\n/g'

【讨论】:

  • 聪明的解决方案;虽然它可能会删除比 OP 要求的更多的 \n 实例,但它可能没问题。请注意,使用转义序列 \r\n 需要 GNU Sed。
  • 除此之外,通过将cat input.txt | tr -d "\n" 更改为tr -d "\n" &lt; input.txt 来丢失UUOC。
【解决方案4】:

感谢大家的所有建议。在查看了所有答案之后。。没有一个完全成功的伎俩...经过一番思考...我想出了

tr -d '\n' <Clicks.txt | tr '\r' '\n' | sed 's/\n/\r\n/g' >test.txt
  1. 删除所有换行符
  2. 将所有回车翻译成换行符
  3. Sed 用回车换行替换所有换行

这对 32mb 文件只需几秒钟即可完成。

【讨论】:

  • 我希望我能启发你。
猜你喜欢
  • 2017-04-12
  • 2016-05-26
  • 2020-05-24
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
相关资源
最近更新 更多