如何替换所有空格而不是换行bash?

时间:2017-08-04 03:56:49

标签: bash

如何在bash中删除所有空格,而不是删除换行符?我正在尝试使用以下命令创建文件:

curl -s https://gateblogs.com/sitemap.xml | grep loc | sed 's/<loc>//g' | sed 's/<\/loc>//g'

,问题是我需要删除所有空格,同时保留所有换行符。

5 个答案:

答案 0 :(得分:2)

这是awk中的一个:

$ curl ... | awk '/<loc>/{gsub(/<\/?loc>|[[:space:]]/,"");print}'

说明:

awk '
/<loc>/ {                            # process only lines with loc tag on it
    gsub(/<\/?loc>|[[:space:]]/,"")  # remove tags and whitespace
    print                            # print
}'

使用xml无能工具处理xml的标准免责声明

修改

我对@rth's answer的评论感到好奇,并进行了一些速度测试。我写了一百万行<loc>https://stackoverflow.com</loc>的记录:

$ awk 'BEGIN{for(i=1;i<=1000000;i++)print " <loc>https://stackoverflow.com</loc>"}' > tehtest

然后继续测试。最好的三个呈现:

$ time cat tehtest |sed 's/<loc>//g' | sed "s/[[:blank:]]*//g" | sed 's/<\/loc>//g' > out1

real    0m39.973s
user    0m42.288s
sys     0m0.600s

$ time cat tehtest | sed -e 's/<loc>//g' -e 's/[[:blank:]]*//g' -e 's/<\/loc>//g' > out2

real    0m40.366s
user    0m40.220s
sys     0m0.212s

$ time cat tehtest|awk '{gsub(/<\/?loc>|[[:space:]]/,"");print}' > out3

real    0m4.053s
user    0m3.988s
sys     0m0.188s

答案 1 :(得分:1)

这不是一个优雅的解决方案,但您可以使用sed删除任何地方的任何空格或标签。喜欢这个

curl -s https://gateblogs.com/sitemap.xml | grep loc | sed 's/<loc>//g' | sed "s/[[:blank:]]*//g" | sed 's/<\/loc>//g'

修改

我感谢@JamesBrown test in his answer。为了表明管道可能比单核应用程序中的多个条件更快,我设计了一个简单的例子。 注意:我设计此示例非常具体,只是为了说明使用管道有利于提高性能的情况。此示例与主要问题略有关联。我可能会得到很多-1但是在管道解决方案更快时显示一个示例可能很有用。

这里生成测试文件的python脚本:

with open("testpipeline","w") as fd:
    for l in xrange(10000):
        for ins in xrange(200):
            fd.write(" <loc> ")
            for k in xrange(30):
                fd.write(" https://stackoverflow.com")
            fd.write(" </loc>                              ")
        fd.write("\n")

测试表明管道的性能优于单核。

$python testpipline.py 
$time cat testpipeline |sed 's/<\/loc>.*<loc>//g' | sed "s/[[:blank:]]*//g" > /dev/null

real    0m27.470s
user    0m38.628s
sys     0m1.232s
$ time cat testpipeline |sed -e 's/<\/loc>.*<loc>//g' -e "s/[[:blank:]]*//g" > /dev/null

real    0m38.382s
user    0m37.716s
sys     0m1.132s

最后,如果我们删除cat,它会比单核

快约30%
$ time sed 's/<\/loc>.*<loc>//g' testpipeline | sed "s/[[:blank:]]*//g" > /dev/null

real    0m26.611s
user    0m38.468s
sys     0m0.268s

我希望它会有所帮助,有人可以发展直觉,这将有助于决定在某些特定情况下什么是最优解决方案。

答案 2 :(得分:1)

不要尝试使用非XML感知工具来解析XML文件。使用XMLStarlet:

curl -s https://gateblogs.com/sitemap.xml | \
  xmlstarlet sel -N sm="http://www.sitemaps.org/schemas/sitemap/0.9" -t -m '//sm:loc' -v . -n <sitemap.xml

...或者,如果您需要在未安装的地方运行,可以使用等效的XSLT模板。如果您有以下内容(当-C参数传递给xmlstarlet sel时,XMLStarlet会以编程方式生成,其中包含想要为其生成模板的查询)extract-locs.xslt

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sm="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
  <xsl:output omit-xml-declaration="yes" indent="no"/>
  <xsl:template match="/">
    <xsl:for-each select="//sm:loc">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="."/>
      </xsl:call-template>
      <xsl:value-of select="'&#10;'"/>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="value-of-template">
    <xsl:param name="select"/>
    <xsl:value-of select="$select"/>
    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

...然后你可以从

获得完全相同的输出
xsltproc extract-sitemap.xslt - <sitemap.xml

答案 3 :(得分:1)

或者,html-xml-utils

curl -s <http_address> | hxnormalize -x | hxselect -c "loc"

其中hxnormalize漂亮打印html文件,hxselect输出给定元素。 -c选项输出匹配元素的内容。如果没有−c,也会打印匹配元素的开始和结束标记。

使用正确的工具完成工作。

答案 4 :(得分:0)

只需添加| column -t

所以,那将是

curl -s https://gateblogs.com/sitemap.xml | grep loc | sed 's/<loc>//g' | sed 's/<\/loc>//g' | column -t