
Исходный файл имеет специальный символ в начале каждой строки. Файл разделен двойным пробелом.
Пример файла данных:
âNAME ABC
âAGE 21
âADDRESS XYZ street ABC city
âCONTACT 13244235
âDOJ 20181212
Я хочу удалить â
первый и специальный символ в каждой строке и преобразовать файл в ;
файл с разделителями (точками с запятой).
Ниже приведен код, который я написал и который отлично работает в UAT, но не работает правильно в PROD:
awk '{ print substr($0,1) }' FILE1.txt | sed 's/ /;/' > FILE2.txt
Выходные данные UAT (желаемый ожидаемый результат):
NAME;ABC
AGE;21
ADDRESS;XYZ street ABC city
CONTACT;13244235
DOJ;20181212
Выход ПРОД:
âNAME;ABC
âAGE;21
âADDRESS;XYZ street ABC city
âCONTACT;13244235
âDOJ;20181212
Тот же код отлично работает в UAT, то есть удаляет первый символ и преобразует файл в файл ;
с разделителем в виде точки с запятой, но в PROD он не удаляет первый специальный символ, а преобразует файл в файл с разделителем в виде точки с запятой.
Вывод locale
:
locale
LANG=en_US.UTF-8
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=
Может ли кто-нибудь мне помочь с этим?
решение1
Я думаю, что проблема может быть связана с кодировкой символов, попробуйте отобразить FILE1.txt
в обоих окружениях с помощью
hexdump -C FILE1.txt
Он может быть закодирован как E-ascii или UTF-8 (см.https://en.wikipedia.org/wiki/%C3%82#Character_mappings)
Чтобы решить вашу проблему, вы можете попробовать сопоставить обе кодировки:
â in UTF-8 â in other encoding
| |
v v
sed 's/\xc3\xa2//' FILE1.txt | sed 's/\xE2//' > FILE2.txt
Другим решением может стать конвертация файла в известную кодировку перед его обработкой.
Не проверять кодировку PROD может быть опасно.
решение2
Поскольку то, что â
вы видите, почти наверняка связано с проблемой кодировки, и если предположить, что все ваши строки должны начинаться с заглавной буквы, вы можете попробовать следующее:
LC_ALL=C sed 's/^[^A-Z]*//; s/ */;/g' FILE1.txt > FILE2
Это запустит команду с использованием C
локали, которая должна гарантировать, что любой ваш символ â
не будет включен в диапазон AZ. Затем команда sed просто удаляет все символы, не входящие в диапазон AZ, из начала каждой строки, а затем преобразует все вхождения двух или более пробелов в ;
.
решение3
пытаться
sed 's/^â//; s/ */;/g' FILE1.txt > FILE2.txt
И поставьте минус, если вам это не подходит.
решение4
Чтобы удалить первый символ каждой строки, необходимо:
cut -c2- # not with the GNU implementation which is currently not multi-byte aware
sed 's/^.//'
awk '{print substr($0, 2)}' # note the 2 instead of 1 as offsets are 1-based
# not with mawk or other non-multi-byte aware awk
# implementations.
Однако следует помнить, что для .
соответствия этому â
символу и substr()
правильной работы он â
должен быть закодирован в соответствии с кодировкой локали (см. вывод locale charmap
).
Чтобы удалить первый символ и заменить все последовательности пробелов на ;
, вы можете сделать следующее:
sed 's/^.//;s/[[:space:]]\{1,\}/;/g'
Или:
awk -v OFS=';' '{$0 = substr($0, 2); $1 = $1; print}'
(хотя будьте осторожны, последний вариант не будет включать завершающий символ ;
для строк, заканчивающихся пробелами, а список пробелов, которые считаются разделителями, зависит от awk
реализации и локали).
Теперь также имейте в виду, что â
(U+00E2) кодируется как байт 0xe2 в кодировке iso8859-1 (она же latin1
и несколько других однобайтовых кодировок). И этот байт 0xe2 также является первым байтом кодировки ряда 3-байтовых символов UTF-8, среди которых есть несколько пробельных символов Unicode (например, пробельные символы U+2000 - U+200B).
Итак, если вы видите â
отображаемый в терминале latin1, возможно, что входные данные на самом деле содержат U+2002 (EN SPACE), например, закодированный в UTF-8 (0xe2 0x80 0x82), и ваш терминал отобразит это 0xe2
как â
и ничего не покажет для 0x80 и 0x82, которые не входят в latin1.
Чтобы избавиться от этого пробела, вам придется либо удалить 1 символ в локали UTF-8, либо удалить 3 символа в однобайтовой локали (например, в локали latin1 или C).