【问题标题】:Replacing Windows CRLF with Unix LF using Perl -- `Unrecognized switch: -g`?使用 Perl 将 Windows CRLF 替换为 Unix LF——“无法识别的开关:-g”?
【发布时间】:2022-12-11 02:40:49
【问题描述】:

问题背景

我们有几千个由 Windows 机器生成的表格数据的大型(10M <行)文本文件,我们需要准备上传到数据库。

我们需要将这些文件的文件编码从cp1252更改为utf-8,用空格替换任何裸 Unix LF 序列(即\n),然后替换 DOS 行结束序列(“CR-LF”,即@ 987654325@) 与 Unix 行结束序列(即 \n)。

dos2unix 实用程序不适用于此任务。

我们最初有一个 bash 函数,它使用 iconvsed 将这些操作打包在一起,iconv 进行编码,sed 处理 LF/CRLF 序列。我正在尝试用 perl 命令替换此 bash 函数的一部分。

示例代码

Based on some helpful code review,我想把这个函数改成perl脚本。

code review 的作者建议如下 perl 将 CRLF(即“\r\n”)替换为 LF(“\n”)。

perl -g -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;'

为什么这比我们以前的更好的解释是完全有道理的,但这条线对我来说失败了:

Unrecognized switch: -g  (-h will show valid options).

更有趣的是,代码审查的作者还建议也可以在 perl 脚本中执行解码/重新编码,但我完全不确定从哪里开始。

问题

请有人解释为什么建议的答案失败 Unrecognized switch: -g (-h will show valid options).

如果有帮助,该行应该接收来自 incov 的管道输入,如下所示(尽管我也有兴趣学习如何使用 perl 执行 redcoding/recoding 步骤):

iconv --from-code=CP1252 --to-code=UTF-8 $1$ | \
perl -g -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;' 
> "$2"

(高度简化的)测试输入示例:

apple|orange|\n|lemon\r\nrasperry|strawberry|mango|\n\r\n

期望的输出:

apple|orange| |lemon\nrasperry|strawberry|mango| \n

【问题讨论】:

  • perl -g -pe 's/(?&lt;!\r)\n/ /g; s/\r\n/\n/g;' 不会在 v5.36.0 中产生错误。

标签: perl sh


【解决方案1】:

错误消息是关于您在perl -g -pe ... 中使用的命令行开关-g。这与正则表达式中的开关无关——它是有效的(但没用,因为一行中只有一个 ,而 -p 逐行读取)。

您正在使用的 perl 版本根本不存在此开关。它只是added with perl 5.36,所以您可能使用的是旧版本。请试试-0777

【讨论】:

  • -g不是gulp的缩写吗? -0777 的别名
  • @dawg:你是对的。此开关存在于最新的 perl 版本中,但不存在于 OP 使用的版本中。固定答案
【解决方案2】:

Perl recently added 命令行开关 -g 作为 Perl v5.36.0 中“gulp 模式”的别名。

这适用于 Perl 版本 v5.36.0:

s=$(printf "Line 1
Still Line 1
Line 2
Line 3
")
perl -g -pe 's/(?<!
)
/ /g; s/
/
/g;' <<<"$s"

印刷:

Line 1 Still Line 1
Line 2
Line 3

但是任何早于 v5.36.0 的 perl 版本,你会这样做:

perl -0777 -pe 's/(?<!
)
/ /g; s/
/
/g;' <<<"$s"
# same

顺便说一句,您正在寻找的转换更容易在这种情况下使用awk,因为您可以有一个多字符记录分隔符。

只需这样做:

awk -v RS="
" '1' <<<"$s"
Still Line 1
Line 2
Line 3

或者,如果你有一个文件:

awk -v RS="
" '1' file

这优于 perl 解决方案,因为文件处理记录是记录(每个文本块由 分隔)而不是将整个文件读入内存。单个 被视为字段分隔符,并自动转换为默认输出字段分隔符——在本例中为 ' '

【讨论】:

    猜你喜欢
    • 2019-09-12
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2011-09-23
    • 2018-08-23
    • 2010-12-08
    • 1970-01-01
    相关资源
    最近更新 更多