sed 在 FreeBSD 和 Linux 上的行为不同吗?

Bar*_*nka 12 freebsd sed

我同时使用 Linux 和 FreeBSD(具体来说,我使用 Debian Linux 和 PC-BSD),我发现sed.

我经常需要将“制表符分隔值”文件转换为“逗号分隔值”。我知道的最简单的方法是使用sed,像这样:

sed 's/\t/,/g' inputFile.txt > outputFile.csv
Run Code Online (Sandbox Code Playgroud)

这在 Linux 上非常有效:它用逗号替换每个选项卡......但在 FreeBSD 上,它不会替换任何东西!!!

我错过了什么吗?FreeBSD 的语法是否与sedLinux的语法不同?

小智 9

也许您应该使用该-E选项(或-r按照手册中的说明)来保持与 GNU Sed 的兼容性。在您的情况下,如果您习惯了 Gnu Sed,则可以安装它(在 FreeBSD 上移植gsed),否则移植脚本需要很长时间。

记住。如果 BSD 上的某些命令与该实用程序的 gnu 版本不同,这并不意味着它已损坏;)


ter*_*don 6

是的,有各种各样的差异,作为我唯一知道的一种行为-i

我从未使用过 BSD,所以我无法真正帮助了解细节,但可能会使用一种解决方法tr

tr '\t' , < inputFile.txt > outputFile.csv
Run Code Online (Sandbox Code Playgroud)

一个令人愉快的副作用是tr应该明显更快。我使用一个包含 50000 行的测试文件在我的 Linux 上进行了测试,每个文件都有 2 个选项卡:

$ time tr '\t' , < foo.txt > /dev/null 

real    0m0.004s
user    0m0.000s
sys     0m0.000s

$ time sed 's/\t/,/g' foo.txt > /dev/null 

real    0m0.039s
user    0m0.036s
sys     0m0.000s
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,不像 GNU sedFreeBSDsed不解释 ANSI C 转义序列,例如\t在正则表达式中。

在这种情况下获得最小公分母的一种方法是使用printf.

tab="$(printf '\t')"
printf '\t\n' | sed 's/'"${tab}"'/,/g'
printf '\t\n' | sed 's/'"$(printf '\t')"'/,/g'
Run Code Online (Sandbox Code Playgroud)

sed -i如果开关或选项紧跟在-i开关之后,则就地文件编辑的行为可以兼容,例如,sed -i -e 's/x/X/g' file适用于 GNUsed和 FreeBSD sed

最新版本的 FreeBSD sed(FreeBSD 8.1 或更高版本)具有-r增加与 GNU 兼容性的开关sed

(此外,在sed正则表达式中使用 POSIX 字符类也是确保兼容性的好方法)。

对于另一种符合 POSIX 的sed实现,请参阅:最小化 - 更小、更便宜、更快的 SED 实现