如何使用 Unix 工具删除括号 [] 之间的所有空格?

如何使用 Unix 工具删除括号 [] 之间的所有空格?

替换括号之间的文本

输入

testing on Linux [Remove white space] testing on Linux

输出

testing on Linux [Removewhitespace] testing on Linux

那么,我们如何删除括号之间的所有空白并实现给定的输出呢?

答案1

如果[,]是平衡的并且不是嵌套的,您可以使用 GNU,awk如下所示:

gawk -v RS='[][]' '
   NR % 2 == 0 {gsub(/\s/,"")}
   {printf "%s", $0 RT}'

即使用[and]作为记录分隔符而不是换行符,并仅删除所有其他记录上的空格。

使用 sed,附加要求内部没有换行符[...]

sed -e :1 -e 's/\(\[[^]]*\)[[:space:]]/\1/g;t1'

如果它们是平衡的但可能像 in 一样嵌套blah [blih [1] bluh] asd,那么您可以使用perl的递归正则表达式运算符,例如:

perl -0777 -pe 's{(\[((?:(?>[^][]+)|(?1))*)\])}{$&=~s/\s//rsg}gse'

另一种可以扩展到非常大的文件的方法是使用(?{...})perl regexp 运算符来跟踪括号深度,如下所示:

perl -pe 'BEGIN{$/=\8192}s{((?:\[(?{$l++})|\](?{$l--})|[^][\s]+)*)(\s+)}
  {"$1".($l>0?"":$2)}gse'

实际上,您也可以一次处理一个字符,如下所示:

perl -pe 'BEGIN{$/=\1}if($l>0&&/\s/){$_=""}elsif($_ eq"["){$l++}elsif($_ eq"]"){$l--}'

该方法可以使用 POSIX 工具来实现:

od -A n -vt u1 |
  tr -cs 0-9 '[\n*]' |
  awk 'BEGIN{b[32]=""; b[10]=""; b[12]=""} # add more for every blank
       !NF{next}; l>0 && $0 in b {next}
       $0 == "91" {l++}; $0 == "93" {l--}
       {printf "%c", $0}'

使用sed(假设 内没有换行符[...]):

sed -e 's/_/_u/g;:1' -e 's/\(\[[^][]*\)\[\([^][]*\)]/\1_o\2_c/g;t1' \
    -e :2 -e 's/\(\[[^]]*\)[[:space:]]/\1/g;t2' \
    -e 's/_c/]/g;s/_o/[/g;s/_u/_/g'

被考虑空白ASCII 字符集中任何水平(SPC、TAB)或垂直(NL、CR、VT、FF...)间距字符上方。根据您所在的区域设置,其他人可能会被包括在内。

答案2

Perl 5.14 解决方案(更短,在我看来更容易阅读,特别是如果您将其格式化为文件中的多行,而不是单行)

perl -pE 's{(\[ .*? \])}{$1 =~ y/ //dr}gex'

这是可行的,因为在 5.14 中,正则表达式引擎是可重入的。在这里,展开并评论:

s{
    (\[ .*? \])         # search for [ ... ] block, capture (as $1)
}{
    $1 =~ y/ //dr       # delete spaces. you could add in other whitespace here, too
                        # d = delete; r = return result instead of modifying $1
}gex; # g = global (all [ ... ] blocks), e = replacement is perl code, x = allow extended regex

答案3

Perl解决方案:

perl -pe 's/(\[[^]]*?)\s([^][]*\])/$1$2/ while /\[[^]]*?\s[^][]*\]/'

相关内容