[php] PHP : 괄호 안의 텍스트를 추출하는 가장 좋은 방법은 무엇입니까?

괄호 사이에 텍스트 세트를 추출하는 가장 좋은 / 가장 효율적인 방법은 무엇입니까? 가능한 가장 효율적인 방법으로 “이 (텍스트)를 제외한 모든 것을 무시”문자열에서 “텍스트”문자열을 얻고 싶다고 가정 해보십시오.

지금까지 내가 생각 해낸 최고는 다음과 같습니다.

$fullString = "ignore everything except this (text)";
$start = strpos('(', $fullString);
$end = strlen($fullString) - strpos(')', $fullString);

$shortString = substr($fullString, $start, $end);

이 작업을 수행하는 더 좋은 방법이 있습니까? 일반적으로 정규식을 사용하는 것이 효율성이 떨어지는 경향이 있다는 것을 알고 있지만 함수 호출 수를 줄일 수 없다면 이것이 가장 좋은 방법일까요? 생각?



답변

나는 정규식을하고 그것을 극복 할 것입니다. 엄청난 성능 문제가 될만큼 충분한 반복 작업을 수행하지 않는 한 코딩이 더 쉽습니다 (그리고 되돌아 보면 이해할 수 있음).

$text = 'ignore everything except this (text)';
preg_match('#\((.*?)\)#', $text, $match);
print $match[1];


답변

따라서 실제로 게시 한 코드는 작동하지 않습니다. substr()'s매개 변수는 $ string, $ start 및 $ length 이고 strpos()'s매개 변수는 $haystack, $needle입니다. 약간 수정 :

$ str = "이 (텍스트)를 제외한 모든 것을 무시합니다";
$ start = strpos ($ str, '(');
$ end = strpos ($ str, ')', $ start + 1);
$ length = $ end-$ start;
$ result = substr ($ str, $ start + 1, $ length-1);

몇 가지 미묘함 : 두 번째 괄호 $start + 1에서 strpos()검색 을 수행하는 동안 PHP를 돕기 위해 offset 매개 변수에 사용 했습니다 . 우리는 증가 $start하나를 줄일 $length경기에서 괄호를 제외 할 수 있습니다.

또한,이 코드에는 오류 검사 가 없습니다 . 를 수행하기 전에 확인 $start하고 $end=== false가 아닌지 확인 하고 싶을 것 substr입니다.

strpos/substr정규식 대 사용에 관해서는 ; 성능면에서이 코드는 정규식을 능가합니다. 그래도 조금 더 말이 있습니다. 나는 먹고 숨을 쉬기 strpos/substr때문에 너무 신경 쓰지 않지만 다른 누군가는 정규식의 간결함을 선호 할 수 있습니다.


답변

정규식을 사용하십시오.

if( preg_match( '!\(([^\)]+)\)!', $text, $match ) )
    $text = $match[1];


답변

이것은 ‘[‘와 ‘]’사이의 모든 텍스트를 추출하여 2 개의 개별 배열 (즉, 한 배열의 괄호 안의 텍스트와 다른 배열의 괄호 밖의 텍스트)을 저장하는 샘플 코드입니다.

   function extract_text($string)
   {
    $text_outside=array();
    $text_inside=array();
    $t="";
    for($i=0;$i<strlen($string);$i++)
    {
        if($string[$i]=='[')
        {
            $text_outside[]=$t;
            $t="";
            $t1="";
            $i++;
            while($string[$i]!=']')
            {
                $t1.=$string[$i];
                $i++;
            }
            $text_inside[] = $t1;

        }
        else {
            if($string[$i]!=']')
            $t.=$string[$i];
            else {
                continue;
            }

        }
    }
    if($t!="")
    $text_outside[]=$t;

    var_dump($text_outside);
    echo "\n\n";
    var_dump($text_inside);
  }

출력 : extract_text ( “hello how are you?”); 다음을 생성합니다.

array(1) {
  [0]=>
  string(18) "hello how are you?"
}

array(0) {
}

extract_text ( “안녕하세요 [http://www.google.com/test.mp3] 잘 지내세요?”); 생산할 것이다

array(2) {
  [0]=>
  string(6) "hello "
  [1]=>
  string(13) " how are you?"
}


array(1) {
  [0]=>
  string(30) "http://www.google.com/test.mp3"
}


답변

이 기능이 유용 할 수 있습니다.

    public static function getStringBetween($str,$from,$to, $withFromAndTo = false)
    {
       $sub = substr($str, strpos($str,$from)+strlen($from),strlen($str));
       if ($withFromAndTo)
         return $from . substr($sub,0, strrpos($sub,$to)) . $to;
       else
         return substr($sub,0, strrpos($sub,$to));
    }
    $inputString = "ignore everything except this (text)";
    $outputString = getStringBetween($inputString, '(', ')'));
    echo $outputString;
    //output will be test

    $outputString = getStringBetween($inputString, '(', ')', true));
    echo $outputString;
    //output will be (test)

strpos () => 문자열에서 첫 번째 발생 위치를 찾는 데 사용됩니다.

strrpos () => 문자열에서 첫 번째 발생 위치를 찾는 데 사용됩니다.


답변

이미 게시 된 정규식 솔루션- \((.*?)\)\(([^\)]+)\)– 열기 및 닫기 괄호 사이 의 가장 안쪽 문자열을 반환하지 않습니다 . 문자열이 Text (abc(xyz 123)있으면 둘 다 a가 아니라 전체 일치로 반환(abc(xyz 123) 됩니다 (xyz 123).

일치 에 괄호가 포함되어야하는 경우, 괄호 안에 다른 열기 및 닫기 괄호가없는 하위 문자열 ( preg_match첫 번째 preg_match_all항목을 가져오고 모든 항목을 가져 오려면 with 사용)과 일치하는 패턴 은 다음과 같습니다.

\([^()]*\)

또는 괄호없이 값을 얻고 자합니다.

\(([^()]*)\)        // get Group 1 values after a successful call to preg_match_all, see code below
\(\K[^()]*(?=\))    // this and the one below get the values without parentheses as whole matches 
(?<=\()[^()]*(?=\)) // less efficient, not recommended

교체 *+문자 1 이상 사이에 존재해야하는 경우 ().

세부 사항 :

  • \( -여는 둥근 괄호 (문자 클래스 외부에서 사용되므로 리터럴 괄호를 표시하려면 이스케이프해야 함)
  • [^()]*0 개 이상의 이외의 자 ()(이주의 ()그 안에 같은 문자 클래스 내에서 이스케이프 할 필요가 없습니다, ()그룹화 및 문자 괄호로 처리됩니다 지정하는 데 사용할 수 없습니다)
  • \) -닫는 둥근 괄호 (문자 클래스 외부에서 사용되므로 리터럴 괄호를 나타 내기 위해 이스케이프되어야 함).

\(\K대체 정규식 의 부분 (이 일치 값에서 일치 하고 생략됩니다 ( \K일치 재설정 연산자 사용). (?<=\()(현재 위치의 바로 왼쪽에가 나타나야 하는 긍정적 인 (룩 비하인드이지만 룩 비하인드 (찾아보기) 패턴이 소비되지 않기 때문에 일치 값에 추가되지 않습니다. 현재 위치의 오른쪽에 문자가 즉시 나타나야 (?=\()하는 긍정적 인 미리보기입니다 ).

PHP 코드 :

$fullString = 'ignore everything except this (text) and (that (text here))';
if (preg_match_all('~\(([^()]*)\)~', $fullString, $matches)) {
    print_r($matches[0]); // Get whole match values
    print_r($matches[1]); // Get Group 1 values
}

산출:

Array ( [0] => (text)  [1] => (text here) )
Array ( [0] => text    [1] => text here   )


답변

function getStringsBetween($str, $start='[', $end=']', $with_from_to=true){
$arr = [];
$last_pos = 0;
$last_pos = strpos($str, $start, $last_pos);
while ($last_pos !== false) {
    $t = strpos($str, $end, $last_pos);
    $arr[] = ($with_from_to ? $start : '').substr($str, $last_pos + 1, $t - $last_pos - 1).($with_from_to ? $end : '');
    $last_pos = strpos($str, $start, $last_pos+1);
}
return $arr; }

이것은 모든 패턴을 배열 형식으로 반환하는 이전 답변에 대한 약간의 개선입니다.

getStringsBetween ( ‘[T] his [] is [test] string [pattern]’)은 다음을 반환합니다.