【问题标题】:Php regex reorder multiple linePHP 正则表达式重新排序多行
【发布时间】:2016-01-17 22:37:43
【问题描述】:
[ITEM 1]  
defname itemname  
name just name  
id 953124  
value 52235  
color red  

[ITEM 2]  
value 522  
name hi  
id 5335  
color yellow  
defname thats 2  

这是我的item.ini 文件,里面有很多东西。如您所见,ITEM 选项订单彼此不同。我想fread 文件和fwrite 它与ITEM 选项的顺序想要(我已经尝试过ofc)。顺序必须是:

ID  
Color  
Defname  
Name  
Value  

【问题讨论】:

  • 虽然这是一个有效的ini(?),但我认为你缺少=来确定namevalue的关系,那么你可以使用parse_ini_file()来解析文件
  • noo 那不是 .ini 文件。它只是一个例子。所以有很多类型在这些值下没有值没有=

标签: php regex preg-replace preg-match fread


【解决方案1】:

你可以这样工作:

// split whole file to get items in an array where each one looks like:
// 1]
// value...
// ...
$raw_items = explode('[ITEM ', file_get_contents('.../item.ini'));

foreach ($raw_items as $item) {
  // turn item lines into an array (see below about PHP_EOL)
  $raw_options = explode(PHP_EOL, trim($item));
  // get item #, which is always the 1st line, drop its ending "]"
  $item_no = substr(trim(array_shift($raw_options), 0, -1);

  foreach ($raw_options as &$option) {
    // turn option line into an array of words
    $option = explode(' ', trim($option));
    // get option name, which is always the 1st word
    $option_name = trim(array_shift($option);
    // populate clean items
    $items[$options[$option_name]] = implode(' ', $option);
  }
}
// then you can use $items[<item_no>][<option_name>]

根据您的具体情况,您可能会遇到有关行分隔符的问题。
如果是这样,请通过替换来摆脱它:

$raw_options = explode(PHP_EOL, trim($item));

通过这个:

str_replace(["\r\n", "\r"], "\n", $item);
$raw_options = explode("\n", trim($item));

【讨论】:

  • 我不能在这里得到错误注意:未定义的索引:defname
  • @cafoob 你测试了吗?值得注意的是查看生成的 $items 并查看它与输入相比如何符合(或不符合)预期。然后,如果您不明白问题出在哪里,请发布这些信息。
【解决方案2】:

这可能是一种奇怪的解决问题的方法,但我们可以使用正则表达式来解决它,就像你的标题一样。

如果我们有这样的字符串:

$string = '
[ITEM 1]  
defname itemname  
name just name  
id 953124  
value 52235  
color red  

[ITEM 2]  
value 522  
name hi  
id 5335  
color yellow  
defname thats 2  ';

我们可以使用preg_replace_callback,它将提取字符串的每一行并将其发送到我们选择的函数进行处理。在这里,我说让我将ITEM 1 的每个部分作为自己的行并将其发送到名为reorder_function 的函数。

我已在表达式上方标记了每个部分,以便您查看它的匹配位置。然后,我简单地打印出新转换的字符串。

// MATCH THE PATTERNS, RUN THE MATCHES THROUGH THE 'reorder_function' FUNCTION AND SAVE THE RESULTS
//                                        1            2      3      4      5      6
$string = preg_replace_callback('~(\[ITEM \d+\]).*?\n(.*?)\n(.*?)\n(.*?)\n(.*?)\n(.*?)($|\n)~', 'reorder_function', $string);


// PRINT OUT THE RESULTS
print $string;

reorder_function 函数看起来有点吓人,但它真的没那么糟糕。大多数情况下,我有很多 cmets 占用空间。它基本上循环遍历包含您希望每个项目的顺序的数组,并且在执行此操作时,它会检查每个匹配项以查看它是否匹配“ID”、“颜色”等。当它找到匹配项时,它会将其写入数组中的特定位置。一旦所有的位置都被填满,数组就会变成一个字符串,[ITEM 1] 的内容会被我们函数的输出覆盖。然后它转到[ITEM 2] 并重复该过程。

// FUNCTION THAT WILL TAKE THE MATCHES AND ORDER THEM APPROPRIATELY
function reorder_function($m) {

    // SET THE DEFAULTS
    $order_array = array( 1 => 'ID', 2 => 'Color', 3 => 'Defname', 4 => 'Name', 5 => 'Value' );
    $final_output_array = array($m[1]); // DEFINE AN ARRAY AND SET THE [ITEM X] TO THE FIRST VALUE


    // LOOP THROUGH THE ORDER ARRAY
    foreach ($order_array AS $key => $val) {

        // LOOP THROUGH THE MATCHES THAT HAVE BEEN FOUND
        foreach ($m AS $match_key => $match_val) {

            // IF THE MATCH FINDS "ID", THEN IT WILL ASSIGN THE VALUE AT POSITION "1"
            // FOR EACH ONE, IT WILL ASSIGN THE VALUE UNTIL WE ARE OUT OF VALUES TO TEST
            if (preg_match('~^\s*'.$val.'\s~i', $match_val)) {
                $final_output_array[$key] = $match_val; 
            }   

        }

    }

    // TURN THE ARRAY INTO A STRING AND SEND IT BACK TO THE preg_replace_callback FUNCTION
    return implode("\n", $final_output_array)."\n";

}

当一切都说完了,我们得到了这个:

[ITEM 1]
id 953124  
color red  
defname itemname  
name just name  
value 52235  

[ITEM 2]
id 5335  
color yellow  
defname thats 2  
name hi  
value 522  

这是一个工作演示:

http://ideone.com/JtYZlx

【讨论】:

  • 好的,非常感谢,但(像往常一样)我有问题要问你。在我的问题字符串中只是一个例子。这些值下也有一些字符串但不会排序?你的代码还能用吗?
  • 他们应该在一般情况下,它只会匹配[ITEM X]换行,Line 1,换行,Line 2,换行,Line 3换行,Line 4,换行,Line 5,换行(或结束)。如果该文件中的其他内容与该格式不匹配,它将不理会它。
  • 再次感谢它的完美运行,但是我该如何处理 [ITEM a] 我的意思是 ITEM “字符串”它不能那样工作
  • 好的,我修复它就像 #([item (.*?)]).*?\n(.*?)\n(.*?)\n(.*?)\n (.*?)\n(.*?)($|\n)#i 那
  • 是的,这样就可以了。方括号内的\d+ 表示“至少一位数”。但是如果你正在寻找不是数字​​的东西,你可以做你所做的(.*?)(尽管你不需要括号)或指定它应该是什么。就像是字母一样,您可以使用这样的字符类来代替[A-Za-z]+。或者如果是字母和/或数字,你可以这样做[A-Za-z0-9]+。但是.*? 只是抓住任何东西直到结束方括号\],所以它也可以正常工作。
猜你喜欢
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2011-02-21
相关资源
最近更新 更多