PHP로 명령줄 스크립트 작성하기: 파트 2, STDIN 읽기

10507 단어
인기 있는 선택은 아니지만 php는 명령줄 스크립트를 작성하는 데 매우 효과적인 언어가 될 수 있습니다. 기능이 풍부하고 bash보다 PHP 기술이 길거나 이미 존재하는 PHP 코드가 있는 경우 명령줄 스크립트에 통합하고 싶은 경우 탁월한 선택이 될 수 있습니다.

이 일련의 기사에서 우리는 php에서 고품질 스크립트를 빌드하는 데 도움이 되는 다양한 기술과 구조를 살펴볼 것입니다.

이 기사는 표준 입력에서 읽는 데 중점을 둡니다.

이전 할부



이것은 시리즈의 두 번째 할부입니다. 첫 번째 기사에서는 명령줄 인수 구문 분석, 현재 환경에서 실행될 수 있도록 스크립트 사전 실행, 스크립트 디자인의 일부 세부 사항 처리에 대해 다루었습니다.

(지금까지) 이 시리즈를 구성하는 기사는 다음과 같습니다.

  • pt 2. handling STDIN input

  • 비행



    여기에서는 STDIN 스트림에서 파이프로 연결된 데이터를 읽는 예제 스크립트를 설계할 것입니다. 이 기능을 사용하려면 다음 두 가지 작업을 수행해야 합니다.
  • 스크립트
  • 에서 읽기를 기다리는 콘텐츠가 STDIN에 있는지 테스트합니다.
  • 실제로 STDIN 입력
  • 읽기
    STDIN 또는 STDOUT 와 같은 Linux 데이터 스트림에 익숙하지 않은 경우 spend a few minutes reading up on them 먼저 하는 것이 좋습니다.

    파이프 입력 읽기



    명령줄 스크립트는 종종 STDIN 에서 파이프된 대로 입력을 받습니다. bash 대신 fish shell을 사용하는 시스템의 모든 사용자를 찾는 이 짧은 작은 파이프라인을 고려하십시오.

    $ cat /etc/passwd | grep "bin/fish"
    gbhorwood:x:1000:1000:grant horwood,,,:/home/gbhorwood:/usr/bin/fish
    

    cat 명령은 파일의 내용을 STDOUT로 덤프합니다. 일반적으로 STDOUT는 터미널로 이동하여 읽을 수 있지만 이 예에서는 | 연산자(파이프)가 STDOUT의 내용을 트랩하고 오른쪽에 있는 다음 명령의 입력으로 사용합니다. 파이프 연산자는 기본적으로 왼쪽 명령의 출력을 오른쪽 명령의 입력으로 '파이프'합니다. 그래서 '파이프'라고 합니다.

    이것은 편리한 기능이며 PHP 스크립트에서 구현하려는 기능입니다. ourfancyscript.php에 추가할 이 함수로 그렇게 해 봅시다.

    #!/usr/bin/env php
    <?php
    
    /**
     * Read contents piped in from STDIN stream
     *
     * @return  String
     */
    function read_piped_input()
    {
        $piped_input = null;
        while ($line = fgets(STDIN)) { // noted STDIN here is not a string
            $piped_input .= $line;
        }
    
        return (string) $piped_input;
    } 
    
    /**
     * Entry point
     */
    $my_piped_in_content = read_piped_input();
    print "piped input is:".PHP_EOL;
    print $my_piped_in_content;
    

    read_piped_input() 함수를 살펴보겠습니다. 여기서 핵심 기능은 fgets 을 사용하여 내용이 소진될 때까지 루프의 STDIN 포인터에서 한 줄씩 읽는 것입니다. 해당 줄은 함께 연결되어 반환됩니다. 임무 완수.

    어떻게 실행되는지 봅시다.

    echo "this is our piped input" | ./ourfancyscript.php
    piped input is:
    this is our piped input
    


    정확히 우리가 기대하는 것.

    파이프 입력 테스트



    제외하고 문제가 있습니다.
    ourfancyscript.php에 대한 입력 없이 STDIN를 실행하면 중단됩니다. 왜요? 결코 오지 않는 입력을 참을성 있게 기다리고 있기 때문입니다.

    이를 해결하기 위해 STDIN에 입력이 있는지 여부를 테스트하고 true를 반환하는 경우에만 파이프에서 읽는 함수를 작성할 것입니다.

    /**
     * Test if there is input waiting on STDIN
     *
     * @return bool
     */
    function test_piped_input()
    {
        $streams = [STDIN]; // note STDIN here is not a string
        $write_array = [];
        $except_array = [];
        $seconds = 0; // zero seconds on timeout since this is just for testing stream change
        $streamCount = @stream_select($streams, $write_array, $except_array, $seconds);
    
        return (boolean) $streamCount;
    }
    


    이 기능의 핵심은 stream_select 명령입니다. stream_select는 기본적으로 스트림의 상태가 변경될 때까지 대기하며 $seconds가 지나면 시간 초과됩니다.

    관심 있는 스트림이기 때문에 배열의 유일한 요소로 STDIN에 전달하고 제한 시간$seconds을 0으로 설정합니다. STDIN 입력이 있거나 없기 때문에 0초를 사용합니다. 스크립트를 실행하기도 전에. 그것을 기다리는 것은 의미가 없습니다. 거기에 있든 없든.

    우리의 명령에 파이프된 데이터가 있는 경우 STDIN는 정의에 따라 '변경'되었으며 stream_select는 0이 아닌 숫자를 반환합니다. 데이터가 우리를 기다리고 있다는 것을 알고 있습니다! 데이터가 없으면 스트림은 변경되지 않고 반환값은 0입니다.

    함께 넣어



    이제 test_piped_input()read_piped_input() 가 있으므로 스크립트에 함께 넣을 수 있습니다.

    /**
     * Entry point
     */
    if (test_piped_input()) {
        $my_stdin_content = read_piped_input();
        print "piped input is:".PHP_EOL;
        print $my_stdin_content;
    }
    


    이제 파이프 연결 스트림 없이 실행하면ourfancyscript.php 진행됩니다. 데이터를 파이프하면 데이터가 처리됩니다.

    이제 전체 스크립트를 살펴보겠습니다.

    #!/usr/bin/env php
    <?php
    
    /**
     * Test if there is input waiting on STDIN
     *
     * @return bool
     */
    function test_piped_input()
    {
        $streams = [STDIN]; // note STDIN here is not a string
        $write_array = [];
        $except_array = [];
        $seconds = 0; // zero seconds on timeout since this is just for testing stream change
        $streamCount = @stream_select($streams, $write_array, $except_array, $seconds);
    
        return (boolean) $streamCount;
    }
    
    /**
     * Read contents piped in from STDIN stream
     *
     * @return  String
     */
    function read_piped_input()
    {
        $piped_input = null;
        while ($line = fgets(STDIN)) {
            $piped_input .= $line;
        }
    
        return (string) $piped_input;
    }
    
    /**
     * Entry point
     */
    if (test_piped_input()) {
        $my_stdin_content = read_piped_input();
        print "piped input is:".PHP_EOL;
        print $my_stdin_content;
    }
    


    다음 단계



    우리 스크립트에 입력을 효과적으로 받는 데는 여전히 다루어야 할 더 많은 근거가 있습니다. 앞으로는 대화식 입력에 대해 살펴보겠습니다.

    좋은 웹페이지 즐겨찾기