gpt4 book ai didi

regex - 如何使用 sed 表达式用单宽替换双宽字符

转载 作者:行者123 更新时间:2023-12-02 20:47:13 26 4
gpt4 key购买 nike

我想使用 sed 表达式将文件中的某些双宽字符替换为它们的单宽等效字符。这并不像预期的那样工作,但表达了我想要做的事情(这是在 bash 脚本中):我已经将字母数字范围与我能想到的其他一些混合在一起,不确定是否需要将其分成基于 if 范围等的两个不同的 -e 参数。
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

    进一步阅读: https://wiki.archlinux.org/index.php/locale

    关于regex - 如何使用 sed 表达式用单宽替换双宽字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50430188/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com