sed出力をprintfのフォーマットされた印刷のようにどのようにフォーマットできますか?

sed出力をprintfのフォーマットされた印刷のようにどのようにフォーマットできますか?

sedはテキストをprintfに似た印刷用の形式の文字列に置き換えることができますか?

次のsedコマンドは、「$ domain」の現在の値で始まる行を変数で指定された複数の値に置き換えます。

/bin/sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain} ${limittype} ${limititem} ${value}/" /etc/security/limits.conf

ただし、そのドメインの長さが異なるため、出力は正しく整列されません。

その後、出力は次のようになります。

#oracle   hard   nproc    131072
oracle hard nproc 666

効果的ですが、読みにくいです。私は次のようなものを得ることを好む

#oracle   hard   nproc    131072
oracle   hard   nproc    666

私が得ることができる最良の結果は次のとおりです。

/bin/sed  "s/\(^${domain}\)\( *\)\(${limittype}\)\( *\)\(${limititem}\)\( *\)\(.*\)/$EXPL#\1\2\3\4\5\6\7\n${domain}\2${limittype}\4${limititem}\6${value}/" /etc/security/limits.conf

しかし、私はこれを行うにはもう少しエレガントな方法が必要だと思います。

これsed oneliners ドキュメント指定された数の文字を使用するいくつかの例が含まれています。

sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # set at 78 plus 1 space

しかし、これはregexp章ではなく章にありますreplacement

ベストアンサー1

理論的には、この作業はsedで完全に実行できますが(Turingが完了したため)、作業に適したツールではありません。

簡単な方法は、sedにタブ文字を挿入してからスペースで後処理することです。すべての列がどこにあるかを確認できる場合は、sed出力をパイプします。expand

</etc/security/limits.conf \
sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain}\t${limittype}\t${limititem}\t${value}/" |
expand -t 10,17,26

\t(Sedがそれをサポートしていない場合は、リテラルタブを使用してください\t。)

列の幅があらかじめわからない場合は、BSDをお試しくださいcolumn便利です。入力ファイル全体を見て、すべての行の長さに対応する列の幅を決定します。

</etc/security/limits.conf \
sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1 ${domain} ${limittype} ${limititem} ${value}/" |
column -t

sedスクリプトがコメントアウトされた行とコメントアウトされていない行の両方を書き換える場合、またはを使用している場合は、コメントアウトされた行がコメントマークの幅を歪めるようにcolumnいくつかの後処理を実行する必要があります。

… | sed '/^#/ s/ //'

代わりに awk を使用できます。機能がありますprintf。追加のボーナスで検索列の内容内の特殊文字(または)を保護する簡単な方法があります.*

</etc/security/limits.conf awk -v domain="$domain" -v limittype="$limittype" -v limititem="$limititem" -v value="$value" '
$1 == domain && $2 == limittype && $3 == limititem  {
    printf "#%-9s %-8s %-9s %s\n%-9s %-8s %-9s %s\n", $1, $2, $3, $4, $1, $2, $3, value; next
}
1 {print}
'

おすすめ記事