我想使用sed
表达式替换文件中找到的单宽度等值的某些双宽字符。这并不像预期的那样有效,但表达了我想要做的事情(这是在bash脚本中):我已经将字母数字范围与我可以想到的其他一些混合在一起,不确定是否需要将其分成两个不同的-e
参数,基于if范围等。
sed -e 's,[0-9a-zA-Z()【】-一],[0-9a-zA-Z\(\)\[\]\-\-],g' ${file} > ${file}.cleaned
文件是tsv(制表符分隔值)文本文件。
根据{{1}}命令,类型为:file
或(在另一种情况下)UTF-8 Unicode text, with CRLF line terminators
示例输入:
UTF-8 Unicode text, with no line terminators
示例输出:
Part Number
123-956-AA
343-213-【E】
XTE-898一(5)
我的系统是Ubuntu16.04,运行在我们的基础映像构建的Docker容器中,该映像是从Part Number
123-956-AA
343-213-[E]
XTE-898-(5)
构建的,它具有phusion/passenger-ruby23:0.9.19
的基本映像(最终到基础),shell是{{ 1}},sed版本为ubuntu:16.04
,GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
命令的结果为:
sed (GNU sed) 4.2.2
更新
选择的解决方案/答案是1)使用locale
命令(正如其他答案也建议),在我的情况下,2)设置如下所示的LL_ALL以避免我得到的错误LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=
命令。确实该范围似乎不适用于y
命令,因此必须单独识别所有字符(正如我之前错误地认为的那样)
y
更新2:
根据其他回答者的建议(一个神秘地消失了),为系统设置的语言环境被进一步调查为解决方案,而不是在命令行设置环境变量。由于这是一个Docker镜像容器环境,我找到了一个解决方案,可以放入我们的基本图像中,解决了基本系统级别的问题。
我已添加到我们的基础Dockerfile:
y
现在LC_ALL=en_US.UTF-8 sed 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()【】-一/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()[]--' file.tsv
命令生成;
# Set the locale
RUN locale-gen en_US.UTF-8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
现在locale
命令的工作原理如下:
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8
作为旁注,我希望stackoverflow提供了一种方法来回答多个答案的答案,因为最初的3个答案(再次,一个消失)都让我得到了解决方案,但我不得不只选择一个。这经常发生。
答案 0 :(得分:2)
如果perl
没问题:
$ perl -Mopen=locale -Mutf8 -pe 'tr/0-9a-zA-Z()【】-一/0-9a-zA-Z()[]--/' ip.txt
Part Number
123-956-AA
343-213-[E]
XTE-898-(5)
-Mopen=locale -Mutf8
将区域设置指定为utf8
tr/0-9a-zA-Z()【】-一/0-9a-zA-Z()[]--/
根据需要翻译字符,也可以使用y
代替tr
可以使用sed (GNU sed) 4.2.2
,但它不支持范围
$ # simulating OP's POSIX locale
$ echo '91A9foo' | LC_ALL=C sed 'y/A9/A9/'
sed: -e expression #1, char 12: strings for `y' command are different lengths
$ # changing to a utf8 locale
$ echo '91A9foo' | LC_ALL=en_US.UTF-8 sed 'y/A9/A9/'
91A9foo
答案 1 :(得分:1)
y/source-chars/dest-chars/
将模式空间中与任何 source-chars 匹配的任何字符与 dest-chars 中的相应字符进行音译。
示例:将“
a-j
”音译为“0-9
”:$ echo hello world | sed 'y/abcdefghij/0123456789/' 74llo worl3
(
/
个字符可以被任何给定的y
命令中的任何其他单个字符统一替换。)source-chars 或 dest中可能会显示
/
(或其他任何使用的字符),\
或换行符的实例-chars 列表,规定每个实例都由\
转义。 source-chars 和 dest-chars 列表必须包含相同数量的字符(在解除转义后)。请参阅GNU coreutils的
tr
命令以获得类似的功能。
请记住,你必须拼出每个角色,范围在这里不起作用。
所以:
sed -e 'y/0123456789abcdefgh[...]/0123456789abcdefgh[...]/'
我会让你拼出所有其他角色。