【问题标题】:How to remove alternating whitespaces from file content如何从文件内容中删除交替空格
【发布时间】:2022-01-26 15:00:16
【问题描述】:

我正在查找一个文件,该文件中偶尔会出现包含交替空格的单词。

例如: h e l l o this is an e x a m p l e

我希望它变成: hello this is an example

我愿意使用任何命令行工具来解决这个问题。我会冒单个字符单词被压扁的风险(因为它们很少出现在我的文件中)。

E. g.:h e l l o this is a r i s k I would take.变成hello this is ariskI would take.

到目前为止,我尝试的是这样,但我想我需要向前看:

sed "s/\([[:alnum:]]\) \([[:alnum:]]\)/\1\2/g" mytextfile.txt

这只会给我: he ll othisisane xa mp le

我只找到有关如何修剪字符串或删除字符串中所有空格的主题。

【问题讨论】:

  • h e l l o this is an e x a m p le 几乎是不可能的,除非你将期望降低到hello this is an examp le
  • @MonkeyZeus 感谢您指出这一点,同时约翰为我纠正了这个错字。

标签: bash shell grep


【解决方案1】:

这样的事情会起作用:

(?:(?<=^)|(?<= ))([^ ]) (?=[^ ] )

https://regex101.com/r/yLccGg/1

【讨论】:

  • 没有强制性的 POSIX 命令行工具可以按照您可能想要的方式理解正则表达式。
【解决方案2】:

使用 node.js 的示例:

$ node -e "fs=require('fs'),fn='input.txt';fs.writeFileSync(fn,fs.readFileSync(fn,{encoding:'utf8'}).replace(/(?<=\b[a-z]) (?![A-Z]|\w\w\w)/g, ''));"

如果空格跟在小写字母后面,并且后面没有大写字母或三个连续的单词字符,则替换空格。

【讨论】:

    【解决方案3】:

    将 GNU awk 用于 patsplit() 和 gensub():

    awk '{
        numFlds = patsplit($0,flds,/\<([^ ] )+[^ ]\>/,seps)
        out = seps[0]
        for ( i=1; i<=numFlds; i++ ) {
            out = out gensub(/([^ ]) /,"\\1","g",flds[i]) seps[i]
        }
        print out
    }' file
    hello this is an examp le
    

    或者,仍然使用 GNU awk,但现在将第三个参数用于 match() 和 gensub():

    $ awk '{
        while ( match($0,/\<(([^ ] )+[^ ]\>)(.*)/,a) ) {
            $0 = substr($0,1,RSTART-1) gensub(/([^ ]) /,"\\1","g",a[1]) a[3]
        }
        print
    }' file
    hello this is an examp le
    

    您必须提供一个算法来解释为什么应该将le 连接到examp 的末尾才能发生这种情况。

    【讨论】:

    • 我认为您缺少)gensub
    • 对不起,我的错...
    【解决方案4】:

    我在您的e x a m p le 的最后一个e 之前插入了一个空格。
    首先你想知道完整的单词。

    echo "h e l l o this is an e x a m p l e"| sed -r 's/\w\w+/=&=/g'
    

    结果

    h e l l o =this= =is= =an= e x a m p l e
    

    现在可以循环删除所有孤立的字符。

    echo "h e l l o this is an e x a m p l e"| 
      sed -r 's/\w\w+/=&=/g;:a;s/( )([^ ])( |$)/\2\3/;ta'
    

    结果

    hello =this= =is= =an=example
    

    接下来用空格替换等号并去掉双空格

    echo "h e l l o this is an e x a m p l e"| 
      sed -r 's/\w\w+/=&=/g;:a;s/( )([^ ])( |$)/\2\3/;ta;s/=/ /g;s/[ ][ ]+/ /g'
    

    等号可以是字符串的一部分。当您使用\r 时,中间结果不会显示清晰的输出字符串,但对于没有\r 的文本会更好。而当你认为一个孤立的I 应该被视为作品时,解决方案是

    echo "h e l l o this is an e x a m p l e that I l i k e"|
      sed -r 's/( I |\w\w+)/\r&\r/g;:a;s/( )([^ ])( |$)/\2\3/;ta; s/\r/ /g;s/[ ][ ]+/ /g'
    

    结果:

    hello this is an example that I like
    

    使用awk 会更简单:

    echo "h e l l o this is an e x a m p l e that I l i k e"|
      awk '
        BEGIN { RS="[ \n]"; FS="" }
        NF==1 { printf("%s",$0); sep=" " }
        $0=="I" { printf(" ")}
        NF>1 { printf("%s%s ", sep, $0); sep =""}
        END {print ""}
      '
    

    所有“单词”都移动到不同的行,当行长变为 1 时,您不需要空格。隔离I 的特殊规则。 sep 用于避免两个多字母单词之间的两个空格,例如this is
    结果:

    hello this is an example that I like
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多