我在几年前编写的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'或空文件的情况下运行上面的示例,它将在新环境中产生相同的错误。
1条答案
按热度按时间puruo6ea1#
编辑:tl;博士:
字符串
在locale处理和ranges的交叉处有一些东西坏了,如果你用
LC_ALL=C
完全关闭locale处理,那部分没问题,但你得不到你的unicode好处,试图绕过range-vetting代码中的任何坏了的东西,让我找到了那个工作的代码。我是如何到达那里的:
我试了一下,没有得到那个,然后我寻找错误。我做了
\x10
,因为我的头十六进制。型
这是locale处理中的一个奇怪的bug。用
LC_ALL=C
运行它对我来说很有效。此外,处理范围,单独指定
\x7f
也可以解决它,而不需要切换区域设置。型
我试着在https://www.jdoodle.com/test-bash-shell-script-online上运行表达式,并选择使用sed v4.7的bash v5.0.011,它没有产生错误,所以这可能不是sed或bash的版本问题。
但是,当我在命令前面添加
LC_ALL=en_US.UTF8
时,它确实会弹出该错误。