次の .txt ファイルがあります。
table columns are:
subject code
date of birth
favorite activities
height (m)
weight (lbs)
test score + standard deviation
color blind
number of siblings
average score
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
table columns are:
... (repeat)
私はこれを次のように変更したいと思います:
subject_8293748/label/NMA.label
subject code 56
date of birth 6.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
subject..(repeat)
n行目ごとにこれをどのように実行できますか?とても感謝しています!
答え1
あなたのデータはどのくらい静的ですか?これは不正行為ですか?
awk '/^[0-9]/ {print $10 "\nsubject code\t\t\t" $1 "\ndate of birth\t\t\t" $2"\nfavorite activities\t\t" $3 "\nheight (m)\t\t\t" $4 "\nweight (lbs)\t\t\t" $5 "\ntest score + standard deviation\t" $6 "\ncolor blind\t\t\t" $7 "\nnumber of siblings\t\t" $8 "\naverage score\t\t\t" $9}' data.txt
答え2
OPに示されている9つの属性名だけでなく、すべての属性名と属性名の数を受け入れるように入力ファイル処理を自動化および一般化できます。
"subject code"
"date of birth"
"favorite activities"
"height (m)"
"weight (lbs)"
"test score + standard deviation"
"color blind"
"number of siblings"
"average score"
awkを使用してこれを行う1つの方法は次のとおりです。
awk -v i=0 -v nAtt=9 '
/table columns are:/ {i+=1;ii=nAtt*(i-1);next}
!/(^$|^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+)/ {ii+=1;a[ii]=$0}
/^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+/
{printf "\n%s\n", $(nAtt+1);
c=0;
for(ii-=nAtt;ii++<1+(nAtt-1)*i;) {c++;printf "%-34s%s\n",a[ii],$c}}
' file.txt
説明する:
- このawk 1行ステートメントは3つの部分で構成され、すべてのようなパターンマッチング
/.../
または次のアンチマッチングで始まります。!/ .../
- ただし、最初に呼び出すときにオプションを持つ2つの外部変数を
awk
渡します-v
。は、データブロックのランク(つまり、入力ファイル内の属性ブロックのシーケンス番号:)を表すのではなく、このソリューションの各データブロックに対して同じでなければならない属性の数を表します。i=0
nAtt=9
i
file.txt
nAtt
awk
最初のパターンマッチング:パターンを見るたびに、table columns are:
新しいデータブロックが次のレコードで始まることを知って、2つのカウンタを設定してi
次ii
のレコードにジャンプします。- 2番目のパターンの一致:読み取り中のレコードが空白行でも一致できる行でもない場合:配列
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
のa
カウンターを増やし、ii
到達するまで属性名文字列で配列を入力し始めます。 - 3番目のパターン一致:レコードが
56 6.18 1307 5.73 167 0.564 2 3 1.7
任意の数の文字と一致する場合は、(nAtt+1)
そのレコードの最初のフィールドを印刷してから、nAtt
属性名と値を1行に1つずつ印刷して、属性名が左揃えになり、長さを超えると切り捨てられます。 34文字。
前に示したように:
- これは、属性ブロックあたりの属性数(nAtt)とブロックごとに異なる(または変更されない)属性名に適用されます。
- マイナーなスクリプトを変更するだけで、ブロックごとにさまざまな属性を持つことが可能で簡単です。
外部変数はに渡すことができます
awk
。たとえば、次のようになります。awk -v i=$i -v nAtt=$nAtt '...'
答え3
これは一つの方法です
awk 'BEGIN {
a[1]="subject code"
a[2]="date of birth"
a[3]="favorite activities"
a[4]="height (m)"
a[5]="weight (lbs)"
a[6]="test score + standard deviation"
a[7]="color blind"
a[8]="number of siblings"
a[9]="average score"
} {
print $10
for(c=0;c++<9;) {
printf "%-34s%s\n",a[c],$c
}
}' file.txt
実行例
$ cat file.txt
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
51 3.18 1307 5.73 167 0.564 2 3 1.7 subject_8293755/label/NMA.label
$ awk 'BEGIN {
a[1]="subject code"
a[2]="date of birth"
a[3]="favorite activities"
a[4]="height (m)"
a[5]="weight (lbs)"
a[6]="test score + standard deviation"
a[7]="color blind"
a[8]="number of siblings"
a[9]="average score"
} {
print $10
for(c=0;c++<9;) {
printf "%-34s%s\n",a[c],$c
}
}' file.txt
subject_8293748/label/NMA.label
subject code 56
date of birth 6.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
subject_8293755/label/NMA.label
subject code 51
date of birth 3.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
$