我正在手动将 Android SMS 数据库传输到我的 iPhone,但没有恢复。由于数字格式为 +1562... iPhone 无法识别该格式并创建新的文本线程。
我正在尝试将其更改+15629876543
为5629876543
和+17114747474
更改为7114747474
,等等。
还有数千个大小不等的数字。任何其他大于或小于 10 位的数字都不应被触及。
这似乎是朝着正确方向迈出的一步:
grep -P '(?<!\d)\d{4}(?!\d)' file
从...获得如何 grep n 位数字的组,但不超过 n 位?
以下是 XML 文件的示例 (编辑:我添加了一个名为的根元素<root>
来制作 XML结构良好)。
<root>
<sms>
<address>+15629876543</address>
<date>1554966601000</date>
<type>1</type>
<body> Yea, should be true. </body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
<sms>
<isMms>1</isMms>
<date>1554968044000</date>
<type>2</type>
<mmsMsgBox>2</mmsMsgBox>
<mmsReaded>1</mmsReaded>
<attachments>
<attachment>
<type>image/jpeg</type>
<body></body>
<name>Screenshot_20190411-002704_Flud.jpg</name>
</attachment>
</attachments>
</sms>
<sms>
<isMms>0</isMms>
<address>+15621234567</address>
<date>1554968778000</date>
<type>1</type>
<isMms>0</isMms>
<address>+17141234534</address>
<date>1558919932000</date>
<type>1</type>
<body>:)</body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
<sms>
<isMms>0</isMms>
<address>+17141234567</address>
<date>1558927846000</date>
<type>1</type>
<body>It's so</body>
<mmsReaded>1</mmsReaded>
<attachments />
<isMms>0</isMms>
<address>+17145757575</address>
<date>1543704644000</date>
<type>1</type>
<body>Hey</body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
<sms>
<isMms>0</isMms>
<date>1543704676000</date>
<type>2</type>
<body>More text</body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
<sms>
<isMms>0</isMms>
<address>+17142323232</address>
<date>1543704736000</date>
<type>1</type>
<body>Lol not even</body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
<sms>
<isMms>0</isMms>
<address>+17141010101</address>
<date>1543704748000</date>
<type>1</type>
<body>You do</body>
<mmsReaded>1</mmsReaded>
<attachments />
</sms>
</root>
答案1
sed
使用编辑 XML 文件时要非常小心。(这是有风险的)。
但您可以轻松使用 XSLT-1.0 处理器(如xsltproc
或)从元素中Saxon
删除前导字符串。因此,请使用以下 XSLT 文件+1
<address>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
<xsl:output method="xml" indent="yes" />
<!-- Identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="sms/address[starts-with(.,'+1')]">
<xsl:copy>
<xsl:value-of select="substring(.,3)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用您的 XML,结果(使用您问题中的 XML)是:
<root>
<sms>
<address>5629876543</address>
<date>1554966601000</date>
<type>1</type>
<body> Yea, should be true. </body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
<sms>
<isMms>1</isMms>
<date>1554968044000</date>
<type>2</type>
<mmsMsgBox>2</mmsMsgBox>
<mmsReaded>1</mmsReaded>
<attachments>
<attachment>
<type>image/jpeg</type>
<body/>
<name>Screenshot_20190411-002704_Flud.jpg</name>
</attachment>
</attachments>
</sms>
<sms>
<isMms>0</isMms>
<address>5621234567</address>
<date>1554968778000</date>
<type>1</type>
<isMms>0</isMms>
<address>7141234534</address>
<date>1558919932000</date>
<type>1</type>
<body>:)</body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
<sms>
<isMms>0</isMms>
<address>7141234567</address>
<date>1558927846000</date>
<type>1</type>
<body>It's so</body>
<mmsReaded>1</mmsReaded>
<attachments/>
<isMms>0</isMms>
<address>7145757575</address>
<date>1543704644000</date>
<type>1</type>
<body>Hey</body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
<sms>
<isMms>0</isMms>
<date>1543704676000</date>
<type>2</type>
<body>More text</body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
<sms>
<isMms>0</isMms>
<address>7142323232</address>
<date>1543704736000</date>
<type>1</type>
<body>Lol not even</body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
<sms>
<isMms>0</isMms>
<address>7141010101</address>
<date>1543704748000</date>
<type>1</type>
<body>You do</body>
<mmsReaded>1</mmsReaded>
<attachments/>
</sms>
</root>
这应该是如所愿的。
答案2
是的,您通常应该避免使用正则表达式来解析结构化数据。但如果您 100% 确信所有+
后跟 11 位数字的出现都是有效目标,那么这是一个非常简单的情况。您可以告诉sed
仅+
当其后跟 11 个数字时才删除(我假设您的意思是 11 而不是 10,因为您的数据中有 11 个):
sed -E 's/\+([0-9]{11}[^0-9]*)\b/\1/' file.xml
启用-E
扩展正则表达式,从而简化语法并能够使用{N}
表示“匹配 N 次”。因此,在这里,我们匹配一个+
(这需要转义,因为\+
否则它表示“匹配 1 个或更多”),后面跟着 11 个数字,然后是 0 个或更多非数字,直到第一个词边界(\b
)。
除 之外的整个匹配项+
都用括号括起来,因此\1
,替换 ,是除 之外的所有内容+
。
由于所有目标数字似乎都在address
标签中,因此稍微安全一点的方法是:
sed -E 's|<address>\+([0-9]{11})<\/address>|<address>\1</address>|' file.xml
或者,如果您的问题可以改写为“+
从第一个非空格字符串所在的行中删除所有内容<address>
”,您可以执行以下操作:
sed -E '/<address>+/{s/\+//}' file.xml