Сделать разницу, игнорировать регистр умлаутов

Мне нужно заставить diff игнорировать регистр моих входных данных. Оба входа содержат немецкие умлауты, такие как ä и Ä. Опция -i успешно заставляет diff игнорировать регистр ввода для других символов, таких как a и A, но не для умляутов:

$ diff -i <(echo ä) <(echo Ä)
1c1
< ä
---
> Ä

Вывод должен быть пустым, поскольку ä и Ä должны восприниматься как одна и та же буква, если регистр игнорируется. Если я попробую это вместо этого:

$ diff -i <(echo a) <(echo A)

Тогда он работает как положено (нет вывода).

Я также попытался установить переменную среды LANG, чтобы diff использовал правильную локаль, но, похоже, это не оказало никакого влияния:

LANG=de_DE.UTF-8 diff -i <(echo ä) <(echo Ä)

Я пробовал разные значения LANG.

Есть ли способ заставить diff игнорировать немецкие умлауты?

(Я использую Ubuntu 22.04 FWIW.)

«Мне нужно, чтобы diff игнорировал регистр моих входных данных» — получайте удовольствие от кодирования, если инструмент еще этого не делает.

Jesper Juhl 07.07.2024 06:25
-i не является стандартным вариантом сравнения - pubs.opengroup.org/onlinepubs/9699919799/utilities/diff.html
jhnc 07.07.2024 07:16

GNU sed распознает их (echo äa:ÄA | sed 's/[[:lower:]]/\U&/g; s/[[:upper:]]/\L&/g'); GNU tr нет (echo äa:ÄA | tr '[:lower:][:upper:]' '[:upper:][:lower:]')

jhnc 07.07.2024 07:19

@jhnc: Ну, у Gnu diff по крайней мере есть -i, и поскольку ОП использует Ubuntu, мы можем догадаться, что он использует это.

user1934428 08.07.2024 08:44

@user1934428 user1934428 правда, я только что указал на это, поскольку «работает так, как ожидалось» в зависимости от реализации будет различаться.

jhnc 08.07.2024 08:47

Я не совсем специалист по Unicode, но, насколько я понимаю, это ошибка в diff, и нормализация, предложенная JosefZ, должна выполняться самим diff. Как насчет сообщить об этой проблеме как об ошибке?

user1934428 08.07.2024 08:50

Исправлены теги для этого вопроса.

user1934428 08.07.2024 08:54

@ user1934428, пожалуйста, посмотрите обновленный ответ…

JosefZ 08.07.2024 14:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, что подход нормализации uconv работает только для латинских символов (но этого достаточно для обработки умлаутов).

Следующий код должен позволять diff -i работать со всеми символами верхнего или нижнего регистра UTF-8 (латиница, греческий, кириллица, адлам и т. д.):

case2ascii()(
    perl -CSD -pe '
        s/[[:lower:]]/c$&/g;
        s/[[:upper:]]/C\l$&/g;
    ' "$@"
)

ascii2case()(
    perl -CSD -pe '
        s{([cC])(.)}{ $1 eq "c" ? $2 : uc($2) }ge;
    ' "$@"
)

diff -i <(echo äæðαа𞤱 | case2ascii) <(echo ÄÆÐΑА𞤏 | case2ascii) | ascii2case
  • кодировать:
    • преобразуйте каждую прописную или строчную букву в строчную и префикс (экранирование) с помощью верхнего или нижнего c в зависимости от ситуации
  • декодировать:
    • найти escape-последовательности и отменить escape, при необходимости преобразовать обратно в верхний регистр

GNU sed также работает:

case2ascii()(
    sed '
        s/[[:lower:]]/c&/g;
        s/[[:upper:]]/C\l&/g;
    ' "$@"
)

ascii2case()(
    sed '
        s/C\(.\)/\u\1/g;
        s/c\(.\)/\1/g;
    ' "$@"
)

использование ascii в названии не совсем правильно, поскольку вывод не полностью ASCII — это только та часть, которую, как мы ожидаем, diff попытается бесчувственно сравнить

jhnc 08.07.2024 06:31

Да, я мог бы записать весь ввод строчными буквами. Но тогда вывод также будет в нижнем регистре, поэтому исходный ввод больше не будет отображаться. Вместо этого я просто хочу игнорировать изменения регистра.

Alfe 15.07.2024 18:33

@Альфе ? вывод не в нижнем регистре — функция ascii2case отменяет все изменения

jhnc 15.07.2024 18:50
Ответ принят как подходящий

Сравните нормализованные строки, см. Формы нормализации Юникода:

 diff -i <(echo ä| uconv -x Any-NFD) <(echo Ä| uconv -x Any-NFD)

Примечание: использовано uconv из sudo apt install icu-devtools

К вашему сведению:

Form   String StrLen Unicode
----   ------ ------ -------
NFC    äÄ          2 \u00e4\u00c4
NFD    äÄ          4 \u0061\u0308\u0041\u0308
NFKC   äÄ          2 \u00e4\u00c4
NFKD   äÄ          4 \u0061\u0308\u0041\u0308

Обновлять:

из info diff[Emphasis mine]:

18.1.1 Обработка многобайтовых символов и символов различной ширины

«diff», «diff3» и «sdiff» рассматривают каждую строку ввода как строку. из однобайтовые символы. В некоторых случаях это может привести к неправильной обработке многобайтовых символов. Например, когда его просят игнорировать пробелы, «diff» неправильно игнорировать многобайтовый символ пробела.

Кроме того, «diff» в настоящее время предполагает, что каждый байт имеет ширину одного столбца, и это предположение неверно в некоторых локалях, например локалях, которые используйте кодировку UTF-8. Это вызывает проблемы с «-y» или Вариант «--side-by-side» из «diff».

Эти проблемы необходимо устранять, не оказывая при этом чрезмерного ущерба производительность утилит в однобайтовых средах.

Команда по интернационализации Технологического центра IBM GNU/Linux предложены патчи для поддержки интернационализированного «diff» (http://oss.software.ibm.com/developer/opensource/linux/patches/i18n/diffutils-2.7.2-i18n-0.1.patch.gz). К сожалению, эти патчи неполные и предназначены для более старых версий. версию «diff», поэтому в этой области необходимо проделать дополнительную работу.

Ubuntu 24.04 LTS (GNU/Linux 5.15.153.1-microsoft-standard-WSL2 x86_64)

Я задавался вопросом о чем-то вроде этого или iconv. Кажется, в целом это не работает: например. æÆ / ðÐ / αΑ / аА / и т. д.

jhnc 08.07.2024 04:47

@jhnc ты прав; ответ дополнен цитатой из info diff

JosefZ 08.07.2024 14:24

это не просто проблема различий GNU. busybox diff работает с кодом вопроса, но не может правильно обработать все символы. например: busybox diff -i <(echo äæðαа𞤱) <(echo ÄÆÐΑА𞤏) (при условии, что это одна и та же строка в нижнем и верхнем регистре)

jhnc 08.07.2024 16:26

Другие вопросы по теме

Похожие вопросы