次のファイルがあります。
OV2 OVI 1VI OV3 3VI
er 23 23 23 23 23
tr 24 24 24 24 24
最初の列と名前に含まれるすべての列を印刷したいと思いますVI
(どの列に文字列が含まれるかは事前に不明です)。上記の例では、出力は次のようになります。
OVI 1VI 3VI
er 23 23 23
tr 24 24 24
すべての列はタブで区切る必要があります。
答え1
perl -lane '$,="\t";
$. == 1 and @A = grep $F[$_] =~ /VI/, 0..$#F;
print @F[0,@A];
' yourfile
結果
ID OVI 1VI 3VI
er 23 23 23
tr 24 24 24
布材
- 最初の行から
$. == 1
文字列を含むフィールドのインデックスを抽出しますVI
。 - 次に、配列内のこれらのインデックスリストを使用して、配列の最初のフィールド+配列にリストされているフィールドを切り取ります
@A
。すでに.YMMVに設定されています。@A
@F
OFS=$,
TAB
アッ
awk -v OFS="\t" '
NR==1{
for ( i=2; i<=NF; i++ )
if ( $i ~ /VI/ )
str = str OFS i
N = split(str, A, OFS)
}{
s = $1
for ( i=2; i<=N; i++ )
s = s OFS $(A[i])
$0 = s
}1
' yourfile
SED
sed -e '
# TAB->spc, multiple spc -> single spc, trim leading/trailing spc
y/ / /;s/[ ]\{2,\}/ /g;s/^[ ][ ]*//;s/[ ][ ]*$//
# only for first line, remove the first field and store remaining in hold area
1{
h
s/[ ]/\
/
s/.*\n//
x
}
# append hold area (which now has 2nd...last fields
# data of the first record) to the present line and
# place a marker at the end of the first field
G
s/[^ ][^ ]*[ ]/&\
/
# setup a do-while loop which progressively either keeps VI data or trims it
:loop
# 1 2 3
s/\(\n\)\([^ ][^ ]*\)[ ]\{0,1\}\(.*\n\)[^ ]*VI[^ ]*[ ]\{0,1\}/ \2\1\3/;tloop
s/\(\n\)[^ ][^ ]*[ ]\{0,1\}\(.*\n\)[^ ][^ ]*[ ]\{0,1\}/\1\2/
/\n\n$/!bloop
# loop ends when the two \ns collide at the end of line
# remove the two \ns and what remains is what you wanted
s///
' yourfile
答え2
アッ解決策:
awk 'BEGIN{FS="[\t ]+"; OFS="\t"}NR==1{for(i=2;i<=NF;i++)
{if($i~/VI/) a[i]; }}{r=$1; for(i in a) r=r OFS $i; print l}' file
出力:
OVI 1VI 3VI
er 23 23 23
tr 24 24 24
FS="[\t ]+"
- 入力フィールド区切り記号OFS="\t"
- 出力フィールド区切り記号NR==1
- 最初になるにはヘッダーワイヤーif($i~/VI/) a[i]
- 一致した場合のフィールド番号の取得VI
r=$1; for(i in a) r=r OFS $i; print r
- 必須フィールド番号を繰り返し、その値を印刷します。
asorti()
順序違反が発生した場合は、関数(インデックスごとに配列を並べ替える)と一緒に以下を使用してください。
awk 'BEGIN{FS="[\t ]+"; OFS="\t"}NR==1{for(i=2;i<=NF;i++)
{if($i~/VI/) a[i]; }}{r=$1; asorti(a,b); for(i in b) {r=r OFS $(b[i])} print r}' file
答え3
Pythonスクリプトソリューション。最初の行を解析し、列リストを作成する作業を実行します。 VIなしの列は「なし」に設定されます。他のすべての行は単語に分割され、比較のためにペアで列リスト項目に関連付けられます。その列項目が None の場合、現在の行の単語は印刷されません。それ以外の場合は、None以外の内容が印刷されます。
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as fd:
indexes = []
for index,line in enumerate(fd):
if index == 0:
columns = line.strip().split()
for i,col in enumerate(columns):
if 'VI' in col or i == 0:
indexes.append(col)
else:
indexes.append(None)
for x in indexes:
if x:
print(x,end=" ")
print("")
continue
for j in zip(line.strip().split(),indexes):
if j[1]:
print(j[0],end=" ")
print("")
注:タブ区切りの出力を取得するには、次のようend=" "
に置き換えます。end="\t"
テスト実行:
$ ./get_colums.py input.txt
ID OVI 1VI 3VI
er 23 23 23
tr 24 24 24