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}'

つまり、改行の代わりに[レコード区切り記号として使用し、他のすべてのレコードからスペースを削除します。]

sedを使用する場合の追加要件は、内部に改行文字を含めないでください[...]

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

バランスが取られているが、潜在的に次のようにネストされている場合は、次のような再帰正規表現演算子を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'

実際には、次のように一度に1文字ずつ処理することもできます。

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ソリューション(短くて読みやすいと思います。特にファイル内で1行ではなく複数行にフォーマットする場合)

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[^][]*\]/'

関連情報