
다음과 같은 파일이 있습니다.
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
. - 이제 array 에 이러한 인덱스 목록이 있으면
@A
그냥 첫 번째 필드 +@A
배열에 나열된 필드를 배열에서 잘라냅니다@F
. 이OFS=$,
(가) 로 설정되었습니다TAB
. YMMV.
앗
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