regex - 如何使用 sed 表达式用单宽替换双宽字符
问题描述
sed
我想使用表达式将文件中的某些双宽字符替换为它们的单宽等效字符。这并不像预期的那样工作,但表达了我想要做的事情(这是在 bash 脚本中):我已经将字母数字范围与我能想到的其他一些混合在一起,不确定是否需要将其分成-e
基于 if 范围等的两个不同参数。
sed -e 's,[0-9a-zA-Z()【】-一],[0-9a-zA-Z\(\)\[\]\-\-],g' ${file} > ${file}.cleaned
这些文件是 tsv(制表符分隔值)文本文件。根据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)
样本输出:
Part Number
123-956-AA
343-213-[E]
XTE-898-(5)
我的系统是在 Docker 容器中运行的 Ubuntu16.04,该容器是从我们的基础镜像构建的,phusion/passenger-ruby23:0.9.19
该容器具有一个基础镜像(最终到基础)ubuntu:16.04
,shell 是GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
,sed 版本是sed (GNU sed) 4.2.2
,locale
命令的结果是:
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=
更新:
选择的解决方案/答案是 1) 使用y
命令(正如其他答案也建议的那样),在我的情况下,2) 如下所示设置 LL_ALL 以避免我使用y
命令时遇到的错误。似乎该范围不适用于该y
命令,因此必须单独识别所有字符(正如我之前错误地认为的那样)
LC_ALL=en_US.UTF-8 sed 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()【】-一/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()[]--' file.tsv
更新 2:
根据其他回答者的建议(其中一个神秘地消失了),为系统设置的语言环境作为一种解决方案被进一步调查,而不是在命令行中设置环境变量。由于这是一个 Docker 镜像容器环境,我找到了一个可以放入我们的基础镜像的解决方案,它解决了基础系统级别的问题。
我已经添加到我们的基础 Dockerfile 中:
# 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
现在该sed
命令的工作方式如下:
sed 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()【】-一/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890()[]--' file.tsv
作为旁注,我希望 stackoverflow 提供了一种将答案归功于多个答案的方法,因为最初的 3 个答案(同样,一个消失了)都让我得到了解决方案,但我只能选择一个。这种情况经常发生。
解决方案
如果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
推荐阅读
- c - 将输入\输出管道从父进程重定向到 cmd 子进程 C/C++ WinApi
- java - 在方法类型参数列表或方法参数中定义有界类型参数
- node.js - 在节点中创建 gcs 存储
- r - 编织文件 r 降价
- javascript - Angular中的客户端IP地址
- reactjs - Typescript 从 React 渲染道具中的元组推断类型
- spring-boot - 嵌套异常是 java.lang.IllegalStateException: Can't configure antMatchers after anyRequest
- html - 如何创建一个内部带有固定元素的扩展 CSS 网格?
- bitbucket - 使用 bitbucket 管道生成自动构建并上传到 ftp 服务器
- python - Django 3.0.7 和 Djongo 嵌入式模型 - “模型尚未加载”