linux 在新环境中使用unicode范围的sed表达式的问题

nfeuvbwi  于 5个月前  发布在  Linux
关注(0)|答案(1)|浏览(75)

我在几年前编写的bash clean脚本中有以下sed范围替换表达式,它在旧环境中工作(或者至少从未出错),但在新环境中失败(出错),我无法确定为什么范围在新旧环境之间无效。
该表达式的目的是从TSV文件中删除不需要的Unicode或控制字符,这些TSV文件用于将数据导入数据库。
一行代码中的表达式示例:

sed -e 's,[\x00\x01-\x08\x0a-\x1f\x7f]\+,,g' file.tsv

字符串

  • 旧环境:Ubuntu v16.04,Bash v4.3.46,GNU Sed v4.2.2
  • 新环境:Ubuntu v20.04、Bash v5.0.17、GNU Sed v4.7

仅在新环境中出错(旧环境中无错误):

/usr/bin/sed: -e expression #1, char 35: Invalid range end


我试着在https://www.jdoodle.com/test-bash-shell-script-online上运行表达式,并选择使用sed v4.7的bash v5.0.011,它没有产生错误,所以这可能不是sed或bash的版本问题。
我不记得我是如何组成字符范围的,也不记得为什么会出现两个范围(两个-),但我觉得我已经足够了解它,可以在很多年前有效地组成它。现在,我正在尝试记住并诊断这个问题,同时迁移到一个新的Docker容器环境,在那里运行脚本。

问题:

有什么突出的地方可以解释为什么这会在一个环境中失败,而在另一个环境中不会?
有没有可能这个表达式需要的不是sed等的版本,而是我在旧环境中做的一个设置?如果你有任何想法,我可以检查和测试。

**注意:**我实际上不需要特定的内容来测试这个,我可以在没有'file.tsv'或空文件的情况下运行上面的示例,它将在新环境中产生相同的错误。

puruo6ea

puruo6ea1#

编辑:tl;博士:

sed 's,[\x00\x01-\x08\x0a\x0b\x0c\x0d\x0e-\x1f\x7f]\+,,g' /dev/null

字符串
在locale处理和ranges的交叉处有一些东西坏了,如果你用LC_ALL=C完全关闭locale处理,那部分没问题,但你得不到你的unicode好处,试图绕过range-vetting代码中的任何坏了的东西,让我找到了那个工作的代码。
我是如何到达那里的:
我试了一下,没有得到那个,然后我寻找错误。我做了\x10,因为我的头十六进制。

$ LC_ALL=en_US.UTF8 sed 's,[\x00\x01-\x08\x10-\x1f\x7f]\+,,g' /dev/null
$ LC_ALL=en_US.UTF8 sed 's,[\x00\x01-\x08\x0a-\x1f\x7f]\+,,g' /dev/null
sed: -e expression #1, char 35: Invalid range end
$ LC_ALL=C sed 's,[\x00\x01-\x08\x0a-\x1f\x7f]\+,,g' /dev/null
$


这是locale处理中的一个奇怪的bug。用LC_ALL=C运行它对我来说很有效。
此外,处理范围,单独指定\x7f也可以解决它,而不需要切换区域设置。

$ sed 's,[\x00\x01-\x08\x0a-\x7e\x7f]\+,,g' /dev/null
$


我试着在https://www.jdoodle.com/test-bash-shell-script-online上运行表达式,并选择使用sed v4.7的bash v5.0.011,它没有产生错误,所以这可能不是sed或bash的版本问题。
但是,当我在命令前面添加LC_ALL=en_US.UTF8时,它确实会弹出该错误。

相关问题