入力する
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[^][]*\]/'