복잡한 상황에서의 인용 규칙

복잡한 상황에서의 인용 규칙

코드 줄을 작성할 때 때때로 특정 문자를 이스케이프 처리해야 하는 경우가 있습니다.

스스로 대답할 수 없는 상황에 부딪혔어요

PHP에서 exec 명령에는 따옴표(')로 묶인 문자열이 필요합니다. 우리는 따옴표(')로 묶인 문자열이 필요한 /bin/bash -c 명령을 호출하려고 합니다.

이 문제에 대한 해결책은 다음과 같습니다.

$line = exec('/bin/bash -c \'read -e -p "Check to confirm string: " -i "'.$preFill.'" input; echo $input\'');

사용자에게 제안하는 텍스트에 문자(')를 삽입하지 않는 한 문제가 없습니다. 대화형 모드에서 php -a를 사용하는 몇 가지 예를 볼 수 있습니다:

php > $preFill = 'I m reach';
php > $line = exec('/bin/bash -c \'read -e -p "Check to confirm string: " -i "'.$preFill.'" input; echo $input\'');
Check to confirm string: I m reach
php >

문제는 $preFill에 "도착했습니다"를 올바른 방식으로 넣기 위해 어떤 이스케이프 규칙을 고려해야 합니까?

답변1

전달된 코드 bash와 전달된 코드 sh( php's 로 시작 )에 대한 exec()참조가 필요합니다.

$preFill = 'I m reach';
$prompt = 'Check to confirm string: ';
$bash_code = 'IFS= read -re -p ' .
              escapeshellarg($prompt) .
              ' -i ' .
              escapeshellarg($preFill) .
              ' input; printf "%s\n" "$input"';
$sh_code = 'exec /bin/bash -c ' . escapeshellarg($bash_code);
$output = exec($sh_code);
echo $output;

너도 잊어버렸어IFS=그리고 -r를 위한read, 그리고쉘 매개변수 확장에 대한 인용문, 그리고 기억하세요echo임의의 데이터와 함께 사용할 수 없습니다.

둘 다 실행 sh하고 bash사용자에게 메시지를 표시하는 것은 과도한 것처럼 보입니다.

답변2

exec('/bin/bash -c \'read -e -p "... " -i "'.$preFill.'" input; echo $input\'');

여기에는 몇 가지 문제가 있습니다. 먼저 셸을 실행하고 있습니다 exec. bash -c ...이는 Bash가 최종적으로 실행하는 코드가 중간 셸에서도 참조되어야 함을 의미합니다. bash셸을 개입시키지 않고 별도의 배열 요소(또는 이와 유사한)의 인수를 사용하여 직접 실행할 수 있는 함수를 사용하면 이를 방지할 수 있습니다 . 이럴 수도 있지proc_open().

$preFill둘째, Bash에 전달하는 코드에 데이터(변수)를 포함시킵니다 . 올바른 인용문과 변수에 대한 좋은 값을 사용하면 이것이 가능하지만 $preFill예를 들어 인용문 자체가 포함될 수 있다면 고통스럽습니다. 사용자가 변수를 제어할 수 있다면 이러한 어려움은 보안 허점이 됩니다. 더 나은 접근 방식은 원하는 값을 명령줄 인수나 환경 변수로 셸에 전달한 다음 셸 프로그램에서 $1값을 참조하거나 가져오는 것입니다 .$val

글쎄, 쉘(또는 두 개)을 실행하는 것은 read꽤 어리석은 것 같습니다. PHP에서 직접 이 작업을 수행하는 더 나은 방법을 찾는 데 시간을 투자하는 것이 더 나을 수도 있습니다.

답변3

귀하의 질문 Y에 대해, bash의 읽기/읽기 기능을 활용하기 위해 PHP를 사용하여 시스템 쉘을 호출할 때 문자열을 적절하게 이스케이프하는 방법에 대해 귀하는 이를 수행하는 방법에 대한 훌륭한 답변을 받았습니다.

이 게시물은 귀하의 질문에 대한 답변을 시도합니다 @roaima가 게시물의 댓글에서 암시했듯이 기본 PHP 솔루션을 사용하면 조잡한 다단계 문자 이스케이프 문제를 피할 수 있습니다.

readline에 대한 PHP 문서포함하다사용자 taneli의 예2009년경에는 외부 쉘 호출에 의존하지 않고도 원하는 작업을 수행하는 방법을 보여줍니다. 예제를 약간 확장했지만 여기서는 taneli의 작업을 반복합니다.

$ cat test.php
<?php

function readline_callback($ret)
  {
    global $prompt_answer, $prompt_finished;
    $prompt_answer = $ret;
    $prompt_finished = TRUE;
    readline_callback_handler_remove();
  }

$prompt_string = 'Check to confirm string: ';

readline_callback_handler_install($prompt_string,
                                  'readline_callback');

$preFill = 'foobar';
for ($i = 0; $i < strlen($preFill); $i++)
{
  readline_info('pending_input', substr($preFill, $i, 1));
  readline_callback_read_char();
}

$prompt_finished = FALSE;
$prompt_answer   = FALSE;

while (!$prompt_finished)
  readline_callback_read_char();

echo 'You wrote: ' . $prompt_answer . "\n"; 

$prompt_string = 'Check to confirm another string: ';
readline_callback_handler_install($prompt_string,
                                  'readline_callback');

$preFill = $prompt_answer;
for ($i = 0; $i < strlen($preFill); $i++)
{
  readline_info('pending_input', substr($preFill, $i, 1));
  readline_callback_read_char();
}

$prompt_finished = FALSE;
$prompt_answer   = FALSE;

while (!$prompt_finished)
  readline_callback_read_char();

echo 'You wrote: ' . $prompt_answer . "\n"; 

?>

산출:

$ php test.php 
Check to confirm string: foobar

is the default" "를 추가 하고 를 누르겠습니다 Enter.

You wrote: foobar is the default
Check to confirm another string: foobar is the default

문자열의 시작 부분 Home을 누르고 넣어 보겠습니다 . 그런 다음 끈 끝에 Now "눌러서 End넣은 다음 누릅니다." is it's own default.Enter

You wrote: Now "foobar is the default" is it's own default.

관련 정보