使用 bash 或 perl 提取两个不同字符串之间的内容
Extracting the contents between two different strings using bash or perl
为此,我已尝试浏览堆栈溢出中的其他帖子,但无法使我的代码正常工作,因此我发布了一个新问题。
以下是文件temp
的内容。
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/<env:Body><dp:response xmlns:dp="http://www.datapower.com/schemas/management"><dp:timestamp>2015-01-
22T13:38:04Z</dp:timestamp><dp:file name="temporary://test.txt">XJzLXJlc3VsdHMtYWN0aW9uX18i</dp:file><dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:file></dp:response></env:Body></env:Envelope>
此文件包含两个文件名test.txt
和test1.txt
的base64编码内容。我想提取每个文件的 base64 编码内容以分别分隔文件 test.txt
和 text1.txt
。
为此,我必须删除 base64 内容周围的 xml 标记。我正在尝试使用以下命令来实现这一目标。但是,它没有按预期工作。
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test.txt">@@g'|perl -p -e 's@</dp:file>@@g' > test.txt
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test1.txt">@@g'|perl -p -e 's@</dp:file></dp:response></env:Body></env:Envelope>@@g' > test1.txt
以下命令:
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test.txt">@@g'|perl -p -e 's@</dp:file>@@g'
产生输出:
XJzLXJlc3VsdHMtYWN0aW9uX18i
<dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:response> </env:Body></env:Envelope>`
然而,在输出中我只期待第一行 XJzLXJlc3VsdHMtYWN0aW9uX18i
。我哪里错了?
当我在命令下 运行 时,我得到了预期的输出:
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test1.txt">@@g'|perl -p -e 's@</dp:file></dp:response></env:Body></env:Envelope>@@g'
它产生以下字符串
lc3VsdHMtYWN0aW9uX18i
然后我可以轻松地将其路由到 test1.txt 文件。
更新
我已经通过更新源文件内容编辑了问题。源文件不包含任何换行符。当前的解决方案在那种情况下不起作用,我已经尝试过但失败了。 wc -l temp
必须输出到 1
。
OS: solaris 10
Shell: bash
sed -n 's_<dp:file name="\([^"]*\)">\([^<]*\).*_ -> _p' temp
- 我添加
->
以显示 link 从文件名到内容,但仅对于内容,只需删除这部分
- posix 版本所以 GNU sed 使用
--posix
- 假设base64编码的内容与周围的标签在同一行(而不是分散在几行,在这种情况下需要一些修改)
感谢 JID 的完整解释
工作原理
sed -n
-n 表示不打印,因此除非明确告知要打印,否则 sed
不会有任何输出
's_
这是用 _
将正则表达式与替换项分开来替换以下正则表达式。
<dp:file name=
常规文本
"\([^"]*\)"
方括号是捕获组,必须转义,除非使用 -r
选项(-r
在 posix 上不可用)。括号内的所有内容都被捕获。 [^"]*
表示任何不是引号的字符出现 0 次或多次。所以实际上这只是捕获了两个引号之间的任何内容。
>\([^<]*\)<
这次再次使用捕获组来捕获>
和<
之间的所有内容
.*
其他都行
_ ->
这是替换,所以用第一个捕获组替换之前正则表达式中的所有内容,然后是 ->
,然后是第二个捕获组。
_p
表示打印行
资源
/usr/xpg4/bin/sed
在这里效果很好。
如果文件仅包含 1 行,/usr/bin/sed
无法按预期工作。
以下命令适用于仅包含一行的文件。
/usr/xpg4/bin/sed -n 's_<env:Envelope\(.*\)<dp:file name="temporary://BackUpDir/backupmanifest.xml">\([^>]*\)</dp:file>\(.*\)__p' securebackup.xml 2>/dev/null
如果没有 2>/dev/null
,此 sed 命令会输出警告 sed: Missing newline at end of file
。
这是因为以下原因:
Solaris 默认的 sed 忽略最后一行不破坏现有脚本,因为在原始 Unix 实现中要求一行以新行终止。
GNU sed 有更宽松的行为,POSIX 实现接受事实但输出警告。
为此,我已尝试浏览堆栈溢出中的其他帖子,但无法使我的代码正常工作,因此我发布了一个新问题。
以下是文件temp
的内容。
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/<env:Body><dp:response xmlns:dp="http://www.datapower.com/schemas/management"><dp:timestamp>2015-01-
22T13:38:04Z</dp:timestamp><dp:file name="temporary://test.txt">XJzLXJlc3VsdHMtYWN0aW9uX18i</dp:file><dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:file></dp:response></env:Body></env:Envelope>
此文件包含两个文件名test.txt
和test1.txt
的base64编码内容。我想提取每个文件的 base64 编码内容以分别分隔文件 test.txt
和 text1.txt
。
为此,我必须删除 base64 内容周围的 xml 标记。我正在尝试使用以下命令来实现这一目标。但是,它没有按预期工作。
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test.txt">@@g'|perl -p -e 's@</dp:file>@@g' > test.txt
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test1.txt">@@g'|perl -p -e 's@</dp:file></dp:response></env:Body></env:Envelope>@@g' > test1.txt
以下命令:
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test.txt">@@g'|perl -p -e 's@</dp:file>@@g'
产生输出:
XJzLXJlc3VsdHMtYWN0aW9uX18i
<dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:response> </env:Body></env:Envelope>`
然而,在输出中我只期待第一行 XJzLXJlc3VsdHMtYWN0aW9uX18i
。我哪里错了?
当我在命令下 运行 时,我得到了预期的输出:
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's@<dp:file name="temporary://test1.txt">@@g'|perl -p -e 's@</dp:file></dp:response></env:Body></env:Envelope>@@g'
它产生以下字符串
lc3VsdHMtYWN0aW9uX18i
然后我可以轻松地将其路由到 test1.txt 文件。
更新
我已经通过更新源文件内容编辑了问题。源文件不包含任何换行符。当前的解决方案在那种情况下不起作用,我已经尝试过但失败了。 wc -l temp
必须输出到 1
。
OS: solaris 10
Shell: bash
sed -n 's_<dp:file name="\([^"]*\)">\([^<]*\).*_ -> _p' temp
- 我添加
->
以显示 link 从文件名到内容,但仅对于内容,只需删除这部分 - posix 版本所以 GNU sed 使用
--posix
- 假设base64编码的内容与周围的标签在同一行(而不是分散在几行,在这种情况下需要一些修改)
感谢 JID 的完整解释
工作原理
sed -n
-n 表示不打印,因此除非明确告知要打印,否则 sed
不会有任何输出's_
这是用 _
将正则表达式与替换项分开来替换以下正则表达式。
<dp:file name=
常规文本
"\([^"]*\)"
方括号是捕获组,必须转义,除非使用 -r
选项(-r
在 posix 上不可用)。括号内的所有内容都被捕获。 [^"]*
表示任何不是引号的字符出现 0 次或多次。所以实际上这只是捕获了两个引号之间的任何内容。
>\([^<]*\)<
这次再次使用捕获组来捕获>
和<
.*
其他都行
_ ->
这是替换,所以用第一个捕获组替换之前正则表达式中的所有内容,然后是 ->
,然后是第二个捕获组。
_p
表示打印行
资源
/usr/xpg4/bin/sed
在这里效果很好。
/usr/bin/sed
无法按预期工作。
以下命令适用于仅包含一行的文件。
/usr/xpg4/bin/sed -n 's_<env:Envelope\(.*\)<dp:file name="temporary://BackUpDir/backupmanifest.xml">\([^>]*\)</dp:file>\(.*\)__p' securebackup.xml 2>/dev/null
如果没有 2>/dev/null
,此 sed 命令会输出警告 sed: Missing newline at end of file
。
这是因为以下原因:
Solaris 默认的 sed 忽略最后一行不破坏现有脚本,因为在原始 Unix 实现中要求一行以新行终止。
GNU sed 有更宽松的行为,POSIX 实现接受事实但输出警告。