web-dev-qa-db-ja.com

Unixの並べ替えは、従来とは異なる区切り文字「±」をフィールド区切り文字として受け入れません

両方試しました

... | sort -k'1,1r' -k'2,2' -t'±'

... | sort -k'1,1r' -k'2,2' -t$'\xC2\xB1'


*$> sort: ±: Invalid argument*

ソートでサポートされていないのではなく、エスケープや特殊文字の処理が不足していることを願っています。

私の設定は:

localhost:~ user$ locale
LANG=
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

localhost:~ user$ sort --version
2.3-Apple (99)
9
Whimusical

ソースコードApple macOS sort を見ると、その FreeBSD Origin から少し変更されています。

特に、FreeBSDの場合と同じ -tオプションの扱いにくい/壊れた処理 が見つかります。

            case 't':
                while (strlen(optarg) > 1) {
                    if (optarg[0] != '\\') {
                        errc(2, EINVAL, "%s", optarg);
                    }
                    optarg += 1;
                    if (*optarg == '0') {
                        *optarg = 0;
                        break;
                    }
                }

ご覧のとおり、-tへの引数は、空(この場合、NULが区切り文字)または単一のbyteまたは、任意の数の\文字で始まり、その後に1バイト(その場合は、そのバイトが区切り文字として使用されます)、または0の後に何かが続く場合(区切り文字はNUL

例:

  • NUL文字の-t ''または-t '\0'、または-t '\\\\\0'または-t '\\0whatever区切り
  • -t '\t'-t '\\\t'区切り文字t
  • -t '\'-t '\\\\\'はバックスラッシュで区切ります。

いずれの場合も、区切り文字は単一のbyteのみにすることができ、その不可解な追加処理がおそらくそこにのみ存在するため、-t '\0'を使用して指定できます。 GNU sort(FreeBSDのsortは、GNU sortでした)との互換性のためのNUL区切り文字、または( [commit-tオプションでさえなかったため)= -t '\\'を使用して\を区切り文字として指定することもできます( GNU sortが受け入れるもの)。

したがって、区切り文字としてマルチバイト文字を使用することはできません。

多くのsort実装では、そこでマルチバイト文字を使用できません。 GNUまたはbusybox sortどちらでもありません。ast-openのsortでもできます。

ここで、並べ替えの前に±を1バイト文字(できれば並べ替えに影響を及ぼさないようにする)と入れ替えて、後で復元することができます。ありがたいことに、FreeBSDのtr、そしておそらくmacOSのtrもマルチバイト文字をサポートしています(GNU trとは逆に):

<input tr '±\1' '\1±' | sort -t $'\1' ... | tr '±\1' '\1±'
26