Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在PHP中检测字符串中的分隔符?_Php_String_Delimiter - Fatal编程技术网

如何在PHP中检测字符串中的分隔符?

如何在PHP中检测字符串中的分隔符?,php,string,delimiter,Php,String,Delimiter,我很好奇,如果你有一个字符串,你将如何检测分隔符 我们知道php可以使用explode()拆分字符串,explode()需要一个分隔符参数 但是,在将分隔符发送到分解函数之前,如何检测分隔符呢 现在我只是将字符串输出给用户,用户输入分隔符。这很好,但我正在寻找一个模式识别的应用程序 我应该在字符串中寻找这种类型的模式识别的正则表达式吗 编辑:我最初未能指定可能存在预期的分隔符集。CSV中可能使用的任何分隔符。因此,从技术上讲,任何人都可以使用任何字符来分隔CSV文件,但更可能使用以下字符之一:逗

我很好奇,如果你有一个字符串,你将如何检测分隔符

我们知道php可以使用explode()拆分字符串,explode()需要一个分隔符参数

但是,在将分隔符发送到分解函数之前,如何检测分隔符呢

现在我只是将字符串输出给用户,用户输入分隔符。这很好,但我正在寻找一个模式识别的应用程序

我应该在字符串中寻找这种类型的模式识别的正则表达式吗

编辑:我最初未能指定可能存在预期的分隔符集。CSV中可能使用的任何分隔符。因此,从技术上讲,任何人都可以使用任何字符来分隔CSV文件,但更可能使用以下字符之一:逗号、分号、竖线和空格

编辑2:下面是我为“确定的分隔符”提出的可行解决方案


确定您认为可能的分隔符(如<代码>、<代码>、<代码>、和<代码> <代码>),并针对每个搜索在字符串中出现的次数(<代码>子目录计数< /代码>)。然后选择出现次数最多的一个作为分隔符,然后分解


尽管这可能不是故障保护,但在大多数情况下它都应该工作;)

我也有同样的问题,我正在处理来自不同数据库的大量CSV,不同的人以不同的方式提取到CSV,有时同一数据集的每次提取都不同。。。在我的convert基类中实现了这样的函数

protected function detectDelimiter() {
    $handle = @fopen($this->CSVFile, "r");
    if ($handle) {
        $line=fgets($handle, 4096);
        fclose($handle);            

        $test=explode(',', $line);
        if (count($test)>1) return ',';

        $test=explode(';', $line);
        if (count($test)>1) return ';';

        //.. and so on
    }
    //return default delimiter
    return $this->delimiter;
}

我做了这样的东西:

$line = fgetcsv($handle, 1000, "|");
if (isset($line[1]))
    {
    echo "delimiter is: |";
    $delimiter="|";
    }
    else
    {
    $line1 = fgetcsv($handle, 1000, ";");
    if (isset($line1[1]))
        {
        echo "delimiter is: ;";
        $delimiter=";";
        }
        else
        {
        echo "delimiter is: ,";
        $delimiter=",";
        }
    }

这只是检查在读取一行后是否有第二列。

我想说,这在99.99%的情况下有效:) 其基本思想是,有效分隔符的数量应逐行相同。 此脚本计算所有行之间的分隔符计数差异。 越小的差异意味着越可能是有效的分隔符

$get_images = "86236058.jpg 86236134.jpg 86236134.jpg";

    //Detection of delimiter of image filenames.
        $probable_delimiters = array(",", " ", "|", ";");

        $delimiter_count_array = array(); 

        foreach ($probable_delimiters as $probable_delimiter) {

            $probable_delimiter_count = substr_count($get_images, $probable_delimiter);
            $delimiter_count_array[$probable_delimiter] = $probable_delimiter_count;

        }

        $max_value = max($delimiter_count_array);
        $determined_delimiter_array = array_keys($delimiter_count_array, max($delimiter_count_array));

        while( $element = each( $determined_delimiter_array ) ){
        $determined_delimiter_count = $element['key'];
        $determined_delimiter = $element['value'];
        }

        $images = explode("{$determined_delimiter}", $get_images);
将其放在一起此函数读取行并将其作为数组返回:

function readCSV($fileName)
{
    //detect these delimeters
    $delA = array(";", ",", "|", "\t");
    $linesA = array();
    $resultA = array();

    $maxLines = 20; //maximum lines to parse for detection, this can be higher for more precision
    $lines = count(file($fileName));
    if ($lines < $maxLines) {//if lines are less than the given maximum
        $maxLines = $lines;
    }

    //load lines
    foreach ($delA as $key => $del) {
        $rowNum = 0;
        if (($handle = fopen($fileName, "r")) !== false) {
            $linesA[$key] = array();
            while ((($data = fgetcsv($handle, 1000, $del)) !== false) && ($rowNum < $maxLines)) {
                $linesA[$key][] = count($data);
                $rowNum++;
            }

            fclose($handle);
        }
    }

    //count rows delimiter number discrepancy from each other
    foreach ($delA as $key => $del) {
        echo 'try for key=' . $key . ' delimeter=' . $del;
        $discr = 0;
        foreach ($linesA[$key] as $actNum) {
            if ($actNum == 1) {
                $resultA[$key] = 65535; //there is only one column with this delimeter in this line, so this is not our delimiter, set this discrepancy to high
                break;
            }

            foreach ($linesA[$key] as $actNum2) {
                $discr += abs($actNum - $actNum2);
            }

            //if its the real delimeter this result should the nearest to 0
            //because in the ideal (errorless) case all lines have same column number
            $resultA[$key] = $discr;
        }
    }

    var_dump($resultA);

    //select the discrepancy nearest to 0, this would be our delimiter
    $delRes = 65535;
    foreach ($resultA as $key => $res) {
        if ($res < $delRes) {
            $delRes = $res;
            $delKey = $key;
        }
    }

    $delimeter = $delA[$delKey];

    echo '$delimeter=' . $delimeter;

    //get rows
    $row = 0;
    $rowsA = array();
    if (($handle = fopen($fileName, "r")) !== false) {
        while (($data = fgetcsv($handle, 1000, $delimeter)) !== false) {
            $rowsA[$row] = Array();
            $num = count($data);
            for ($c = 0; $c < $num; $c++) {
                $rowsA[$row][] = trim($data[$c]);
            }
            $row++;
        }
        fclose($handle);
    }

    return $rowsA;
}
函数readCSV($fileName) { //检测这些纤度计 $delA=数组(“;”、“,”、“|”、“\t”); $linesA=array(); $resultA=array(); $maxLines=20;//要分析以进行检测的最大行数,可以更高以获得更高的精度 $lines=计数(文件($fileName)); 如果($lines<$maxLines){//如果行小于给定的最大值 $maxLines=$lines; } //载重线 foreach($delA作为$key=>$del){ $rowNum=0; if($handle=fopen($fileName,“r”)!==false){ $linesA[$key]=array(); 而(($data=fgetcsv($handle,1000,$del))!==false)和($rowNum<$maxLines)){ $linesA[$key][]=计数($data); $rowNum++; } fclose($handle); } } //计数行分隔符编号彼此不符 foreach($delA作为$key=>$del){ 回显'try for key='。$key.'delimeter='。$del; $discr=0; foreach($linesA[$key]作为$actNum){ 如果($actNum==1){ $resultA[$key]=65535;//此行中只有一列具有此delimeter,因此这不是我们的分隔符,请将此差异设置为高 打破 } foreach($linesA[$key]作为$actNum2){ $discr+=abs($actNum-$actNum2); } //如果是真实的delimeter,则该结果应最接近于0 //因为在理想(无错误)情况下,所有行都有相同的列号 $resultA[$key]=$discr; } } var_dump($resultA); //选择最接近0的差异,这将是我们的分隔符 $delRes=65535; foreach($resultA as$key=>$res){ 如果($res<$delRes){ $delRes=$res; $delKey=$key; } } $delimeter=$delA[$delKey]; 回声“$delimeter=”。$delimeter; //吵架 $row=0; $rowsA=array(); if($handle=fopen($fileName,“r”)!==false){ while(($data=fgetcsv($handle,1000,$delimeter))!==false){ $rowsA[$row]=数组(); $num=计数($data); 对于($c=0;$c<$num;$c++){ $rowsA[$row][]=trim($data[$c]); } $row++; } fclose($handle); } 返回$rowsA; }
我也有同样的问题。我的系统将从客户端接收CSV文件,但它可以使用“;”、“、”或“”作为分隔符,并且我可以改进系统,这样客户端就不必知道哪个是(他们永远不会知道)

我搜索并找到了此库:


非常好且易于使用。

分隔符是什么样子的?我对让用户指定分隔符的逻辑感到困惑。这样做的目的是什么?为什么不直接使用任何一个常用的定界符并完成它呢?@Alex如果任何东西都可以是定界符,那么你所要求的听起来很不现实。模式匹配以检测分隔符是一项非常重要的任务,您按照此规范提出的任何内容都将是O(n^c)。其中n是所有可能分隔符的集合,c是字符串长度。丑陋…好吧,您可以构建一个启发式系统,尝试从可能的分隔符列表中识别分隔符(
,;/|
)。根据需要,您可以对字符在文件中出现的次数进行计数分析(毕竟,我认为分隔符在每行中至少会出现几次)…这注定会经常失败。如果我的内容中包含大量的
||||||?如果是为了实验目的,它可以是一个开始。否则,这样的构造将导致系统崩溃。一种选择是,如果计数超过一个,或者它们很接近,则逐行遍历文件并计数出现的次数。数字最稳定的一个(不同