端末とシェルスクリプトを使用したさまざまなエンコード/Unicodeの説明

端末とシェルスクリプトを使用したさまざまなエンコード/Unicodeの説明

私はキーマッピングスクリプト(ある言語キーボードレイアウトから別の言語キーボードレイアウトへのキーマッピング)を作成しています。すべてがうまくいくように努力した後、私はすべてのプログラム(Perl、Python)でさまざまな文字が異なるように扱われることを発見しました。次に、端末(kitty、gnome-terminal - 重要ではありません)で単純なテストスクリプト(今や簡略化)を実行します。

python -c 'import sys;print(len(sys.argv[1]))' テスト

予想される結果を得た。

3

しかし、sh / bash(unix&utf-8)ファイルで実行すると:

#!/usr/bin/env bash
# or
#!/bin/sh
python -c 'import sys;print(len(sys.argv[1]))' テスト

私は得る( ./test.sh):

9

これがUTF-8エンコーディング/デコード/アップグレード/ダウングレードがPerlで機能しない理由です(ターミナルで手動でコマンドを実行すると、これらの追加のエンコーディング機能なしで動作できます)。

今質問があります。まったく同じコマンドが実行環境(ターミナルエミュレータとシェルスクリプト)によって異なる結果を提供するのはなぜですか?この問題をどのように解決できますか?

修正する:

私のことを忘れました:

alias python='python3'

したがって、Pythonの場合、python3明示的に実行すると、どちらの場合もすべてが同じになります。しかし、一方でPerlの場合:

echo 'print length $ARGV[0];' | perl -l -- - テスト

それは同じように機能しますが、どちらの場合も印刷されます9。 Perlの他のバージョンはありません。私のバージョンは5.30.0です(どちらの場合も印刷されたバージョンはまったく同じです)。 Python3のように動作するようにPerl自体にいくつかのコードを追加する必要があります(1 Unicode文字の長さは1〜3バイトではなく1バイトです)?

答え1

これはシェルに関するものではなく、pythonpython3とpython2を使用して同じコマンドを明示的に実行して再現できます。

$ python3 -c 'import sys;print(len(sys.argv[1]))' テスト
3
$ python2 -c 'import sys;print(len(sys.argv[1]))' テスト
9

特定の実行可能ファイルのフルパスを使用しないため、端末とスクリプトの両方が.txtにリストされているディレクトリで見つかったpython最初のパスを使用します。あなたの場合、非対話型シェル(スクリプトの実行)にあるものは対話型シェル(ターミナル内)にあるのとは異なり、前者では明らかにPython2実行可能ファイルを指します。pythonPATHPATHPATHpython

なぜこれがあるのか​​わかりません。お使いの設定と使用しているOSについて詳しく知る必要があります。ただし、これを提供するシステムを使用していると仮定すると、簡単な解決策は次のpython3スクリプトを呼び出すことですpython

python3 -c 'import sys;print(len(sys.argv[1]))' テスト

またはフルパスを使用してください(参照type -a python)。

/usr/bin/python -c 'import sys;print(len(sys.argv[1]))' テスト

これにより、結果は常に一貫したままになります。

関連情報