3

デフォルトは(1 つのスペース) であり、これは特殊なケースであり、「スペース、タブ、および改行」を意味し、デフォルトFSは(1 つのスペース)であることを知っています。" "OFS" "

2つの特定のフィールドが分​​離された正確な文字列を知ることは可能ですか、またはより一般的には、入力が与えられた方法で出力形式に入力形式を反映させることは可能ですか?

$ cat foo
foo bar        quux  # single space, single tab
 foo  bar   quux     # single space, double space, triple space

コマンド:

$ awk '{ $2 = "blah" }1' foo

次の結果が得られます。

foo blah        quux  # single space, single tab
 foo  blah   quux     # single space, double space, triple space

それ以外の:

foo blah quux         # single space, single space according to default OFS
foo blah quux         # single space, single space according to default OFS
4

3 に答える 3

3

subgsubまたはこの場合は機能する可能性がありますが、OFSの再計算をトリガーしないため、gensubこれは でのみ実行し$0、 では実行しないでください。$1-n

ただし、行の正しいテキスト部分(フィールド)を置き換える置換を確実にするために、スペース/タブを計算して正規表現パターンを記述する必要があります。(@Ed のように)

gawk をお持ちの場合は、 を使用できます。次の方法FPATで労力を節約できます。

 awk  'BEGIN{FPAT="\\s*\\S*\\s*";OFS=""} {sub("\\S*","bar",$2)}1' file

これにより、必要な結果が生成されます。

例: (<tab>見えませんが、そこにあります)

kent$  cat file
foo bar qq
 foo  bar   qqq
kent$  awk  'BEGIN{FPAT="\\s*\\S*\\s*";OFS=""} {sub("\\S*","xxx",$2)}1' file
foo xxx qq
 foo  xxx   qqq
于 2013-05-06T14:07:46.200 に答える
3

OFS の値を区切り記号として使用して awk がレコードを再コンパイルしない限り、フィールドに値を割り当てることはできません。代わりに、正規表現を使用してレコード全体を記述し、関心のあるフィールドが存在する場所に存在するレコードの一部を置き換えます。たとえば、GNU awk を使用する場合 (他の awk では、match()/substr() および [[:space:]] を使用):

$ cat foo
foo bar quux         # single space, single tab
 foo  bar   quux     # single space, double space, triple space

$ awk '{ print gensub(/^(\s*(\S+\s+){1})\S+(.*)/,"\\1blah\\3","") }' foo
foo blah quux         # single space, single tab
 foo  blah   quux     # single space, double space, triple space

置き換えたいフィールドの前にある多くのフィールドに合わせて1inを変更します。{1}

$ awk '{ print gensub(/^(\s*(\S+\s+){2})\S+(.*)/,"\\1blah\\3","") }' foo
foo bar blah         # single space, single tab
 foo  bar   blah     # single space, double space, triple space

$ awk '{ print gensub(/^(\s*(\S+\s+){3})\S+(.*)/,"\\1blah\\3","") }' foo
foo bar quux         blah single space, single tab
 foo  bar   quux     blah single space, double space, triple space

gawk には、split() のように機能する patsplit() という名前の関数も含まれていますが、結果の文字列にフィールドを格納するだけでなく、フィールド間のスペースも 2 番目の配列に格納するため、これらの配列でループを使用して取得できます。それがより明確な場合は、元のスペース:

$ awk '{ nf = patsplit($0,fld,/\S+/,sep); fld[2]="blah"; for (i=1;i<=nf;i++) printf "%s%s", sep[i-1], fld[i]; print "" }' foo
foo blah quux         # single space, single tab
 foo  blah   quux     # single space, double space, triple space

$ awk '{ nf = patsplit($0,fld,/\S+/,sep); fld[3]="blah"; for (i=1;i<=nf;i++) printf "%s%s", sep[i-1], fld[i]; print "" }' foo
foo bar blah         # single space, single tab
 foo  bar   blah     # single space, double space, triple space

patsplit() が各レコードを分割する方法は次のとおりです。

$ awk '{ nf = patsplit($0,fld,/\S+/,sep); print "\n" $0; for (i=0;i<=nf;i++) print "<" i ":" fld[i]
 ":" sep[i] ">" }' foo

foo bar quux         # single space, single tab
<0::>
<1:foo: >
<2:bar: >
<3:quux:         >
<4:#: >
<5:single: >
<6:space,: >
<7:single: >
<8:tab:>

 foo  bar   quux     # single space, double space, triple space
<0:: >
<1:foo:  >
<2:bar:   >
<3:quux:     >
<4:#: >
<5:single: >
<6:space,: >
<7:double: >
<8:space,: >
<9:triple: >
<10:space:>
于 2013-05-06T14:01:33.253 に答える
2

この問題に対する一般的な解決策はありませんが、フィールドの一部として先頭の空白を含めるGNU awkことで巧妙にこれを行うことができます。FPAT

$ awk '{sub(/\S+/,"blah",$2)}1' OFS= FPAT='\\s*\\S+' file
foo blah quux         # single space single tab
 foo  blah   quux     # single space double space triple space

メソッドは問題固有であり、置換の正規表現であり、問​​題FPATごとに変更する必要がありますが、awk.

于 2013-05-06T14:09:47.220 に答える