除了出现在括号中的逗号外,如何拆分逗号?
How can split on a comma except where it appears in brackets?
我想这样拆分:
之前:
TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D
之后:
TEST_A
TEST_B
TEST_C (with A, B, C)
TEST_D
如何拆分?
此次正则表达式无济于事,因此您将不得不遍历字符。
事实是,正则表达式不是很了解上下文。因此,you can’t use regular expression to parse HTML。这就是为什么我们最好自己遍历字符串。
function magic_split($str) {
$sets = array(''); // Sets of strings
$set_index = 0; // Remember what index we’re writing to
$brackets_depth = 0; // Keep track if we’re in brackets (or not)
// Iterate through entire string
for($i = 0; $i < strlen($str); $i++) {
// Skip commas if we’re not in brackets
if($brackets_depth < 1 && $str[$i] === ',') continue;
// Add character to current list
$sets[$set_index] .= $str[$i];
// Store brackets depth
if($str[$i] === '(') $brackets_depth++;
if($str[$i] === ')') $brackets_depth--;
if(
$i < strlen($str) - 1 && // Is a next char available?
$str[$i+1] === ',' && // Is it a comma?
$brackets_depth === 0 // Are we not in brackets?
) $sets[++$set_index] = ''; // Add new set
}
return $sets;
}
$input = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
$split = magic_split($input);
此问题的正确解决方案将完全取决于您用于识别各个元素的规范。
如果您希望每个都以 TEST_
开头,那么您可以使用正则表达式相当简单地解决它:
$input = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
$matches = preg_split('/,\s*(?=TEST_)/', $input);
var_dump($matches);
输出:
array(4) {
[0]=>
string(6) "TEST_A"
[1]=>
string(6) "TEST_B"
[2]=>
string(21) "TEST_C (with A, B, C)"
[3]=>
string(6) "TEST_D"
}
使用 lookahead assertion 测试在下一项的开头是否存在 TEST_
,将逗号后跟空格拆分字符串。
您想匹配:
- 一个不包含左括号,也不包含逗号的单词:[^(,]+
- 括号之间的表达式:\([^(]+\)
- or not...并且没有返回匹配项,所以它变成: (?:\([^(]+\))?)
- 昏迷,然后是一些 space : ,[\s]*
PHP代码:
$ar=preg_split("#([^(,]+(?:\([^(]+\))?),[\s]*#", "$input,", -1,
PREG_SPLIT_DELIM_CAPTURE |PREG_SPLIT_NO_EMPTY)
编辑:如果你在括号外没有昏迷,它就不起作用。
你必须像上面修改的那样在 $input 之后添加一个额外的昏迷。
您只需要展开逗号-space 并忽略括号内的任何逗号-space。 (*SKIP)(*FAIL)
将消耗所有括号表达式并处理它们,以便它们不用作分隔符。
代码:(Demo)
$text = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
var_export(preg_split('~\([^)]*\)(*SKIP)(*FAIL)|, ~', $text));
输出:
array (
0 => 'TEST_A',
1 => 'TEST_B',
2 => 'TEST_C (with A, B, C)',
3 => 'TEST_D',
)
我想这样拆分:
之前:
TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D
之后:
TEST_A
TEST_B
TEST_C (with A, B, C)
TEST_D
如何拆分?
此次正则表达式无济于事,因此您将不得不遍历字符。
事实是,正则表达式不是很了解上下文。因此,you can’t use regular expression to parse HTML。这就是为什么我们最好自己遍历字符串。
function magic_split($str) {
$sets = array(''); // Sets of strings
$set_index = 0; // Remember what index we’re writing to
$brackets_depth = 0; // Keep track if we’re in brackets (or not)
// Iterate through entire string
for($i = 0; $i < strlen($str); $i++) {
// Skip commas if we’re not in brackets
if($brackets_depth < 1 && $str[$i] === ',') continue;
// Add character to current list
$sets[$set_index] .= $str[$i];
// Store brackets depth
if($str[$i] === '(') $brackets_depth++;
if($str[$i] === ')') $brackets_depth--;
if(
$i < strlen($str) - 1 && // Is a next char available?
$str[$i+1] === ',' && // Is it a comma?
$brackets_depth === 0 // Are we not in brackets?
) $sets[++$set_index] = ''; // Add new set
}
return $sets;
}
$input = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
$split = magic_split($input);
此问题的正确解决方案将完全取决于您用于识别各个元素的规范。
如果您希望每个都以 TEST_
开头,那么您可以使用正则表达式相当简单地解决它:
$input = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
$matches = preg_split('/,\s*(?=TEST_)/', $input);
var_dump($matches);
输出:
array(4) {
[0]=>
string(6) "TEST_A"
[1]=>
string(6) "TEST_B"
[2]=>
string(21) "TEST_C (with A, B, C)"
[3]=>
string(6) "TEST_D"
}
使用 lookahead assertion 测试在下一项的开头是否存在 TEST_
,将逗号后跟空格拆分字符串。
您想匹配:
- 一个不包含左括号,也不包含逗号的单词:[^(,]+
- 括号之间的表达式:\([^(]+\)
- or not...并且没有返回匹配项,所以它变成: (?:\([^(]+\))?)
- 昏迷,然后是一些 space : ,[\s]*
PHP代码:
$ar=preg_split("#([^(,]+(?:\([^(]+\))?),[\s]*#", "$input,", -1,
PREG_SPLIT_DELIM_CAPTURE |PREG_SPLIT_NO_EMPTY)
编辑:如果你在括号外没有昏迷,它就不起作用。 你必须像上面修改的那样在 $input 之后添加一个额外的昏迷。
您只需要展开逗号-space 并忽略括号内的任何逗号-space。 (*SKIP)(*FAIL)
将消耗所有括号表达式并处理它们,以便它们不用作分隔符。
代码:(Demo)
$text = 'TEST_A, TEST_B, TEST_C (with A, B, C), TEST_D';
var_export(preg_split('~\([^)]*\)(*SKIP)(*FAIL)|, ~', $text));
输出:
array (
0 => 'TEST_A',
1 => 'TEST_B',
2 => 'TEST_C (with A, B, C)',
3 => 'TEST_D',
)