Как использовать выражение sed для замены символов двойной ширины на одну ширину - PullRequest
0 голосов
/ 20 мая 2018

Я хочу заменить определенные символы двойной ширины, найденные в файле, их эквивалентами одинарной ширины, используя выражение 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)

Моя система - Ubuntu16.04, работающая в контейнере Docker, построенном из нашего базового образа, который построен из phusion/passenger-ruby23:0.9.19, который имеет базовый образ (в конечном счете, базовый) ubuntu:16.04, оболочка 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

Asпримечание: я хотел бы, чтобы stackoverflow предоставил способ дать оценку нескольким ответам, поскольку первоначальные 3 ответа (опять же один исчезли) помогли мне найти решение, но мне пришлось выбрать только один.Это часто случается.

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Если 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()[]--/ перевод символов по мере необходимости, также можно использовать *Можно использовать 1011 * вместо 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

0 голосов
/ 20 мая 2018

Использование команда y :

y/source-chars/dest-chars/

Транслитерация любых символов в пространстве образца, которые соответствуют любому из источника -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 должны содержать одинаковое количество символов (после удаления).

См. *Команда 1040 * из GNU coreutils для аналогичной функциональности.

Просто имейте в виду, что вам нужно прописать каждый символ, диапазоны здесь не сработают.

Итак:

sed -e 'y/0123456789abcdefgh[...]/0123456789abcdefgh[...]/'

Я позволю вам разобрать все остальные символы.

...