Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.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
Linux PHP';在bash中的s preg_替换,具体情况_Linux_Bash_Preg Replace_Sh - Fatal编程技术网

Linux PHP';在bash中的s preg_替换,具体情况

Linux PHP';在bash中的s preg_替换,具体情况,linux,bash,preg-replace,sh,Linux,Bash,Preg Replace,Sh,我需要清理包含PHP序列化值的mysql转储(我使用sed搜索/替换URL) 在PHP中,我会这样做: <?php $ret_string = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.mb_strlen('$2').':\"$2\";'", $string ); ?> 我已经用mynewurl.com替换了myurl.com,因此它现在看起来像: a:3:{s:7:"string1";s:4:"test";s:3:"url";s:17

我需要清理包含PHP序列化值的mysql转储(我使用sed搜索/替换URL)

在PHP中,我会这样做:

<?php

$ret_string = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.mb_strlen('$2').':\"$2\";'", $string );

?>
我已经用mynewurl.com替换了myurl.com,因此它现在看起来像:

a:3:{s:7:"string1";s:4:"test";s:3:"url";s:17:"http://mynewurl.com";s:7:"string2";s:‌​4:"test";}
我需要更改的是字符串的长度,以反映新字符串(s:17)的长度,以便最终字符串变为:

a:3:{s:7:"string1";s:4:"test";s:3:"url";s:19:"http://mynewurl.com";s:7:"string2"‌​;s:4:"test";}

我的sql转储中有很多这样的文件,它是文件系统中的一个文件。虽然域已更改,但url可能有其他路径,因此字符串长度不同。在regexp中执行此操作的问题是,regexp不适合JSON或PHP序列化字符串等结构化文本。如果您知道您的输入数据将始终遵循特定的结构,那么您可以“伪造”一些东西,但这样编写的代码会随着时间的推移而出现问题。事情总是随着时间的推移而改变。如果你能避免这种黑客行为,最好这样做

我们到底想解决什么问题?您是否无法在需要进行此更改的主机上运行PHP?序列化数据在PHP中处理起来会容易得多,即使您制作了一个很小的shell可执行PHP脚本来处理它

[ghoti@pc ~]$ cat indexrepl
#!/usr/bin/env php
<?php

// Usage: indexrepl index newcontent [string]

if ($argc < 4) {
  $s='a:3:{s:7:"string1";s:4:"test";s:3:"url";s:16:"http://myurl.com";s:7:"string2";s:4:"test";}';
} else {
  $s=$argv[3];
}

$a=unserialize($s);
$a[$argv[1]]=$argv[2];

print serialize($a) . "\n";

[ghoti@pc ~]$ 
[ghoti@pc ~]$ 
[ghoti@pc ~]$ ./indexrepl url http://example.com/
a:3:{s:7:"string1";s:4:"test";s:3:"url";s:19:"http://example.com/";s:7:"string2";s:4:"test";}
[ghoti@pc ~]$ 
[ghoti@pc ~]$ s='a:3:{s:7:"string1";s:4:"test";s:3:"url";s:19:"http://example.com/";s:7:"string2";s:4:"test";}'
[ghoti@pc ~]$ ./indexrepl string1 foo "$s"
a:3:{s:7:"string1";s:3:"foo";s:3:"url";s:19:"http://example.com/";s:7:"string2";s:4:"test";}
[ghoti@pc~]$cat索引REPL
#!/usr/bin/env-php

我最终得到了一个php-r解决方案。在bash中这样做可能会有很多行,我认为:

mv "$DATA_DIR/final.sql" "$DATA_DIR/final.sql.1"
php -r  "echo preg_replace('!s:(\\d+):\\\\\\\"(.*?)\\\\\\\";!e', \"'s:'.strlen( str_replace (array('\\\\r', '\\\\n', '\\\\t'), ' ', '\$2') ) .':\\\\\\\"\$2\\\\\\\";'\", file_get_contents('$DATA_DIR/final.sql.1') );" >"$DATA_DIR/final.sql"
rm "$DATA_DIR/final.sql.1";

在bash中,您可以使用
-r code
命令行选项调用
php
,但我只会对1行程序这样做,因为启动php解释器会有开销。我正要使用
sed
,但你要求的是纯
bash
解决方案。@YzmirRamirez:当人们说“in bash”时,他们有时指的是“纯bash”,但更多时候指的是像
sed
这样的常用工具,等等。@Laurent:如果你展示一些样本数据和期望的结果,这会有所帮助。@Dennis@Yzmir是的,我只需要在bash脚本中完成,sed等就可以了。下面是一个字符串示例:
a:3:s:7:“string1”;s:4:“测试”;s:3:“url”;s:17:“http://myurl.com";s:7:“第2条”;s:4:“测试”;}我已经替换为,所以它的长度(s:17)应该更改,以便最后的字符串变成:
a:3:s:7:“string1”;s:4:“测试”;s:3:“url”;s:19:“http://mynewurl.com";s:7:“第2条”;s:4:“测试”;}我的sql转储中有很多这样的文件,它是文件系统中的一个文件。虽然域已更改,但url可能有其他路径,因此不同的字符串长度+1可用于编辑您的问题。你不知道当人们在评论中提出他们真正的问题时有多沮丧-感谢您花时间回答,但正如我所说,我必须在Wordpress SQL转储中进行替换,该转储包含大量要更正的序列化数据,因此我不能像这样用PHP取消序列化/序列化数据。如果我编写的脚本在bash脚本中使用,它将生成可靠的可重新序列化输出。您的问题没有提到Wordpress或此数据的来源或去向,也没有提到您需要运行此数据的主机上是否有PHP CLI。用一个示例更新了我的答案。我指定它是一个“包含PHP序列化值的mysql转储”,变量的序列化表示是插入sql查询。。。
[ghoti@pc ~]$ cat strings.txt
a:1:{s:3:"foo";s:3:"bar";}
a:1:{s:3:"foo";s:3:"baz";}
a:1:{s:3:"foo";s:5:"snert";}
[ghoti@pc ~]$ while read line; do ./indexrepl foo test "$line"; done < strings.txt
a:1:{s:3:"foo";s:4:"test";}
a:1:{s:3:"foo";s:4:"test";}
a:1:{s:3:"foo";s:4:"test";}
[ghoti@pc ~]$ 
mv "$DATA_DIR/final.sql" "$DATA_DIR/final.sql.1"
php -r  "echo preg_replace('!s:(\\d+):\\\\\\\"(.*?)\\\\\\\";!e', \"'s:'.strlen( str_replace (array('\\\\r', '\\\\n', '\\\\t'), ' ', '\$2') ) .':\\\\\\\"\$2\\\\\\\";'\", file_get_contents('$DATA_DIR/final.sql.1') );" >"$DATA_DIR/final.sql"
rm "$DATA_DIR/final.sql.1";