2012-06-20 1 views
6

이 질문의 근본 원인은 Perl에 대한 새로운 옵션/인수 처리 모듈 (OptArgs)에 대한 테스트를 작성하려는 나의 시도입니다. 물론 이것은 this 질문에 대한 답변을 기반으로하고있는 @ARGV 파싱을 포함합니다. 이것은 I18N :: Langinfo :: CODESET [1]이 정의 된 시스템에서 잘 작동합니다. langinfo(CODESET) 내가 적어도 관찰 된 동작을 기반으로 최선의 노력을하고 싶은 사용할 수없는 시스템에Perl에서 외부 명령에 유니 코드 인수를 전달하는 방법은 무엇입니까?

. 그러나 지금까지 테스트 한 결과, 어떤 시스템에서는 심지어 외부 스크립트에 unicode 인수를 제대로 전달할 수 없음을 나타냅니다. "test_script는"단순히 수행하는 펄 스크립트입니다

나는 다양한 시스템에 다음과 같은 뭔가를 실행하는 관리 가지고 print Dumper(@ARGV) :

use utf8; 
my $utf8 = '¥'; 
my $result = qx/$^X test_script $utf8/; 

내가 발견 한 것은 FreeBSD의에 test_script 바이트를 수신되는 Perl의 내부 형식으로 디코딩 할 수 있습니다. 그러나 OpenBSD와 Solaris에서 test_script는 유니 코드 대체 문자 (두 번?)만을 포함하는 문자열 "\x{fffd}\x{fffd}"을 표시합니다.

qx 연산자의 기본 메커니즘을 모르겠습니다. 나는 어느 쪽이든 exec 또는 쉘 아웃이라고 추측하지만 파일 핸들과 달리 (인코딩을 위해 binmode 할 수 있음) 내가 원하는 것을 수행하는 방법을 알지 못한다. 이 문제에 대해서는 system()과 동일합니다. 그래서 내 질문은 내가 올바르게 위에서 무엇을하지 않는가? 그렇지 않으면 OpenBSD와 Solaris에서 Perl, 쉘 또는 환경과 다른 점은 무엇입니까?

[1] 실제로 CPAN 테스터 결과에 따르면 Linux 만 생각합니다.

업데이트 (X2) : 내가 현재 가지고있는 cpantester의 설정을 통해 그것의 방법을 실행하는 Schwern에의 가설을 테스트하기 위해 다음 그들이 통해 올 때

use strict; 
use warnings; 
use Data::Dumper; 

BEGIN { 
    if (@ARGV) { 
     require Test::More; 
     Test::More::diag("\npre utf8::all: " 
       . Dumper({ utf8 => $ARGV[0], bytes => $ARGV[1] })); 
    } 
} 

use utf8; 
use utf8::all; 

BEGIN { 
    if (@ARGV) { 
     Test::More::diag("\npost utf8::all: " 
       . Dumper({ utf8 => $ARGV[0], bytes => $ARGV[1] })); 
     exit; 
    } 
} 

use Encode; 
use Test::More; 

my $builder = Test::More->builder; 
binmode $builder->output,   ':encoding(UTF-8)'; 
binmode $builder->failure_output, ':encoding(UTF-8)'; 
binmode $builder->todo_output, ':encoding(UTF-8)'; 

my $utf8 = '¥'; 
my $bytes = encode_utf8($utf8); 

diag("\nPassing: " . Dumper({ utf8 => $utf8, bytes => $bytes, })); 

open(my $fh, '-|', $^X, $0, $utf8, $bytes) || die "open: $!"; 
my $result = join('', <$fh>); 
close $fh; 

ok(1); 
done_testing(); 

나는 다양한 시스템에 결과를 게시합니다을. 이것의 타당성 및 정확성에 대한 의견은 감사 할 것입니다. 올바른 테스트를 위해 이 아니고이 아님을 유의하십시오. 위의 목적은 다른 시스템에서받은 것을 비교할 수있게하는 것입니다.

해상도 : 실제 근본적인 문제는 내 질문이나 아래의 Schwern의 답변으로 해결되지 않은 것으로 판명되었습니다. 내가 발견 한 것은 일부 cpantesters 머신은 아스키 로케일 만 설치/사용 가능하다는 것입니다. 이러한 유형의 환경에서 UTF-8 문자를 프로그램에 전달하려고 시도해서는 안됩니다. 그래서 결국 내 문제는 잘못된 테스트 조건, 잘못된 코드가 아니었다.

qx 연산자 또는 utf8::all 모듈이 매개 변수가 외부 프로그램에 전달되는 방식에 영향을 미치지 않음을 나타 내기 위해 지금까지 아무 것도 보지 못했습니다. 중요한 구성 요소는 LANG 및/또는 LC_ALL 환경 변수로, 외부 프로그램에 어떤 로케일이 실행되고 있는지 알려주는 것입니다.

그런데 내 코드가 모든 시스템에서 작동하고 있다는 본래의 주장 I18N : Langinfo :: CODESET 정의가 잘못되었습니다.

+0

관련 참고 사항에서 BSD는 다른 방식으로 손상된 것 같습니다. 나는 FreeBSD에 ssh 세션을 통해 유니 코드 문자를 입력 할 수도 없다 - 그 결과로 이상한 터미널 동작이 발생한다. –

+0

unicode-via-ssh는 사용중인 터미널과 두 시스템의'TERM '에 크게 의존합니다. – sarnold

+0

OS X에서 문제를 재현 할 수는 없지만 [utf8 :: all] (https://metacpan.org/module/utf8::all)을 사용하여 유니 코드를 비롯한 대부분의 유니 코드 기능을 활성화 할 수 있습니다 '@ ARGV'. 'qx'는'utp8 :: all'이 파일 핸들을 유니 코드로 존중시키는'open' pragma의 영향을받을 수도 있습니다. – Schwern

답변

1

qx 셸을 호출하면 방해가 될 수 있습니다.

이를 피하려면 utf8::all을 사용하여 모든 Perl 유니 코드 부두를 켜십시오. 그런 다음 open 함수를 사용하여 셸을 피하면서 프로그램에 파이프를 엽니 다.

use utf8::all; 
my $utf8 = '¥'; 

open my $read_from_script, "-|", "test_script", $utf8; 
print <$read_from_script>,"\n"; 
+0

3 인자 버전의 open을 사용하는 것을 피하는 것이 좋습니다. 그러나 utf8 :: all이'open' 함수 나 기본'exec' 호출에 대한 인수에 어떤 영향을 미치는지 알 수는 없습니다. –

+0

utf8 :: all의 출처를 살펴보면 실제로 [@ ARGV] 인코딩에 대한 가정을합니다. (http://stackoverflow.com/questions/2037467/how-can-i-treat-command-line -arguments-as-utf-8-per-perl)이 경고했다. 그러나 그것은이 질문에서 화제를 내리고있다. –

+0

@MarkLawrence'utf8 :: all'은'open'pragma를 통해 효과가 있습니다. 구체적으로''open "을 사용하십시오 : STDOUT에 UTF-8을 사용하게함으로써 아마도 std"'가 파이프 열림 효과를 나타냅니다. "다른 사람이 알아서 모듈을 사용하게"하는 좋은 예입니다. 그리고 네,'@ ARGV '의 인코딩에 대한 가정을하고 있습니다. 당신은 비록 당신이 ASCII를 가정하고 있지 않더라도 UTF-8이 꽤 안전한 내기라는 가정을해야합니다. 불행히도 어휘로 할 수있는 것은 아닙니다. – Schwern

관련 문제