
次のサンプル入力ファイルがあります。
Apple Orange Gold Silver Spoon Apple Orange Gold
Apple
Apple Orange
Apple Orange
Mango Gold Silver Spoon Apple Orange
15〜20番目の位置が空白であることを確認し、それを文字列に置き換える必要がありますSilver
。また、50〜70位のコンテンツを完全に置き換える必要があります。xxxxxxxxxxxxxxxxxxxxx
答え1
より小さい行を処理する方法に応じて(上記の説明を参照)、sed
解決策は次のとおりです。
sed -e '/^.\{14\} \{6\}/s/^\(.\{14\}\) \{6\}/\1Silver/' \
-e '/^.\{49\}./s/^\(.\{49\}\)\(.\{1,21\}\)\?\(.*\)\?/\1xxxxxxxxxxxxxxxxxxxxx\3/'
そして、よりクリーンでエラーの少ないGNUawk
バージョンは次のとおりです。
awk '
BEGIN { FIELDWIDTHS = "14 6 29 21 999" ; OFS = "" }
$2 == " " { $2 = "Silver" }
$4 != "" { $4 = "xxxxxxxxxxxxxxxxxxxxx" }
{ print }
'
説明する:
1.) sed:このsed
コマンドは、2つの独立した置換で構成されています。最初は「シルバー」ケースを処理し、2番目は「xxx ...」ケースを処理します。交換形態sed
は次のとおりです。
/pattern/s/pattern2/replacement/
最初のパターンが一致した場合、対応する置換が実行され、その行の場合、2 番目のパターンが置換式で置き換えられます。詳細はsed
一般的に秘密です。
.
-どんなキャラクターでも
\{14\}
- 前のサブ式を繰り返します(ここでは14回)。
\(expr\)
- 代替文字列で等として参照できるサブ式\1
。\2
ここで、実際の数字はn番目の角括弧式として定義されます。
\?
– 前のサブ式がオプション部分であることを指定します。
2.) アーク:プログラムはこのセクションを一度実行し、左側のawk
条件が真の場合にのみBEGIN
データファイルの各行の後続のセクションとその右側のタスクを実行します。{...}
FIELDWIDTHS
$i
- 各フィールドが(一部のフィールド番号iの場合)として処理できるように、入力行のデータフィールドの幅を指定します。
OFS=""
- 空の文字列、出力フィールドに追加の区切り文字を含めないでください。
$2 == " "
- 2番目のフィールド(仕様に従ってFIELDWIDTHS
)に6つのスペースが含まれている場合は、対応する文字列に置き換えます。
$4 != ""
- 4番目のフィールドにデータが含まれている場合は、「xxx ...」文字列に置き換えます。
{ print }
- 1 つまたは 2 つの以前のジョブによって変更された、または変更されていない行を表示する現在の行の無条件印刷
答え2
sed 's/^\(.\{14\}\) /\1Silver/
s/^\(.\{49\}\).\{20\}/\1xxxxxxxxxxxxxxxxxxxxx/
' <infile >outfile
はい、私の考えでは。
答え3
Perlを使用して、21文字未満の文字を含む行(最初の置換の場合)と70文字未満の文字を含む行(2番目の置換の場合)を削除する必要があるとします。
< inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile
21文字未満の文字を含む行(最初の置換の場合)と70文字未満の文字を含む行(2番目の置換の場合)を最初にスペースで埋める必要があると仮定するには、awk
+Perlを使用します。
< inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile
コマンド#1失敗:
< inputfile
:コンテンツを「s」inputfile
にリダイレクトします。perl
stdin
-p
:Perlにこの行を印刷するように強制します。-e
: Perl に引数からプログラムラインを読み込むように強制します。> outputfile
perl
:コンテンツをstdout
次にリダイレクトします。outputfile
コマンド#2分割:
< inputfile
inawk
:コンテンツを 's'inputfile
にリダイレクトします。awk
stdin
{printf "%-70s", $0}
:行の文字数が70になるまで、各行にスペースを埋めます。|
:awk
パイプでstdout
接続perl
stdin
-p
:Perlにこの行を印刷するように強制します。-e
: Perl に引数からプログラムラインを読み込むように強制します。> outputfile
perl
:コンテンツをstdout
次にリダイレクトします。outputfile
代替#1分析:
s
: 置換を実行するためのアサーション/
: 検索モード開始^
: 行の先頭に一致します。(
: キャプチャグループを開始.{14}
:14回表示される任意の文字と一致)
: グループキャプチャの停止{6}
:6番登場するキャラクターと一致
/
:検索モードを停止/交換モードを開始$1
:キャプチャされたグループに置き換えられましたSilver
Silver
: 文字列の追加/
: 交換モードの停止
代替#2分析:
s
: 置換を実行するためのアサーション/
: 検索モード開始^
: 行の先頭に一致します。(
: キャプチャグループを開始.{49}
:すべての文字の49項目に一致します。)
: グループキャプチャの停止.{21}
:21番登場する任意の文字と一致/
:検索モードを停止/交換モードを開始$1
:キャプチャされたグループに置き換えられましたxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxx
: 文字列の追加/
: 交換モードの停止
出力例:
:~/tmp$ cat inputfile
Apple Orange Gold Silver Spoon Apple Orange Gold
Apple
Apple Orange
Apple Orange
Mango Gold Silver Spoon Apple Orange
~/tmp$ < inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple OrangeSilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxxld
Apple
Apple Orange
Apple OrangeSilver
Mango SilverGold Silver Spoon Apple Orange
~/tmp$ < inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple OrangeSilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxxld
Apple Silver xxxxxxxxxxxxxxxxxxxxx
Apple OrangeSilver xxxxxxxxxxxxxxxxxxxxx
Apple OrangeSilver xxxxxxxxxxxxxxxxxxxxx
Mango SilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxx
~/tmp$