如果文件包含以“+1”开头的数字,如何修改文件

如果文件包含以“+1”开头的数字,如何修改文件

我正在手动将 Android SMS 数据库传输到我的 iPhone,但没有恢复。由于数字格式为 +1562... iPhone 无法识别该格式并创建新的文本线程。

我正在尝试将其更改+156298765435629876543+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&apos;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

相关内容