繁体   English   中英

如何删除单行txt文件的行尾符号(使用sed/awk)?

[英]How to delete end-of-line sign (using sed/awk) of a single-line txt file?

仅当“列表”是包含单行(URL)而没有结束行尾符号(“ $”)。 我试过了

sed -e 's/\r$//g'

sed -e 's/^M//g'

但我只能在文本编辑器中手动删除结尾的“$”,转到文件的最后一行(即第二行)并按键盘上的退格键。

将包含数百个 URL 的主文件拆分为单行文件并一次调用 php 函数是没有问题的,但是必须有另一种简单的方法(sed,awk?)来删除结尾的“$”文件中(仅)行的结尾。

您的文件中没有$ $是一个用于在正则表达式中表示字符串结束的符号(就像^表示字符串开始)。 在一次操作一行的工具中,它正在处理的字符串的结尾也是行的结尾,因此使用面向行的工具的人经常将$误认为是行尾,因为在上下文中工具是一样的。 $也用于其他工具(例如cat -E )作为行尾指示符。

一些术语/定义:

  • \\r是脚本中用于生成或匹配CR (回车)字符^M (控制-M)、ASCII 13 的转义序列
  • \\n是脚本中用于生成或匹配LF (换行符)字符^J (control-J)、ASCII 10 的转义序列
  • $是脚本中用于指示end-of-string (通常也是行结束)的正则表达式元字符,也被工具用于在显示文本时指示行end-of-line
  • \\n (即单独的LF )在 UNIX 中被认为是换行符
  • \\r\\n (即CRLF )被认为是 DOS 中的换行符(请参阅为什么我的工具输出会覆盖自身以及如何修复它?

所以当你这样做时:

$ printf 'foo\n' | cat -vE
foo$

这并不意味着在foo的末尾有一个$ ,它只是cat显示一个$来告诉你行尾的位置。 当你这样做时:

$ printf 'foo\r\n' | cat -vE
foo^M$

^M (control-M)明确地向您展示了由\\r生成的CR (回车)字符,但$没有明确地向您展示LF (换行)生成的^J (control-J)字符由\\n代替,它专门显示不同的字符$以显示行尾。 如果它确实向您显示^J s,那么所有内容都将连接在一行上,这将很难阅读。 考虑一下阅读这个的难易程度:

$ printf 'the\nquick\nbrown\nfox\n' | cat -vE
the$
quick$
brown$
fox$

与如果输出是这样的:

$ printf 'the\nquick\nbrown\nfox\n' | some_other_tool
the^Jquick^Jbrown^Jfox^J

您永远无法执行以下任一操作:

$ printf 'foo\nbar\n' | sed 's/$//' | cat -vE
foo$
bar$

$ printf 'foo\nbar\n' | sed 's/\n//' | cat -vE
foo$
bar$

要删除 LF,因为 sed 在读取输入时已经消耗了 LF 并且$本身不是换行符,它是一个元字符,可让您在正则表达式中说“匹配行尾”(在这种情况下,因为结束默认情况下,输入字符串的末尾是 sed 的行尾)。

您可能会问 - 如果 sed 在读取输入时消耗了 LF 那么为什么在每行输出的末尾都有 LF? 答案是 sed 向每个输出行添加一个 LF,因此它输出的是一个有效的 POSIX 文本文件(如果不终止 LF,您就没有 POSIX 文本文件,因此任何后续工具对它所做的都是未定义的行为)。

但是,如果您使用的工具一次不读取一行,则可以删除 LF。 GNU sed 有一个-z选项来读取 NUL 分隔的文本而不是 LF 分隔的文本,在这种模式下你可以删除LF字符:

$ printf 'foo\nbar\n' | sed -z 's/\n//' | cat -vE
foobar$

现在您可以看到$ (字符串结尾元字符)与\\n (匹配 LF 字符的转义序列)有何不同:

$ printf 'foo\nbar\n' | sed -z 's/$//' | cat -vE
foo$
bar$

$ printf 'foo\nbar\n' | sed -z 's/\n/<LF>/' | cat -vE
foo<LF>bar$

$ printf 'foo\nbar\n' | sed -z 's/$/<EOS>/' | cat -vE
foo$
bar$
<EOS>$

所以“你如何用 sed 删除 LF”的快速答案? 这是 GNU sed 吗:

$ printf 'foo\nbar\n' | sed -z 's/\n//g'
foobar$

并且如果您没有 GNU sed(或者实际上即使您这样做,因为假设没有 NUL 作为输入的 POSIX 文本文件,上述内容会立即将整个输入读入内存),那么您应该只使用 awk:

$ printf 'foo\nbar\n' | awk -v ORS= '1'
foobar$

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM