다음과 같은 텍스트가 많이 있습니다.
K1 CM1 TN1 CT14 D01
K2 CM2 TN2 CT15 D02
K3 CM3 TN3 CT16 D03
K4 CM4 TN4 CT17 D04
K5 CM5 TN5 CT18 D05
K6 CM6 TN6 CT19 D06
K7 CM11 TN7 CT20 D07
K8 CM12 TN8 D08
TW10 CM15 TN9 D09
TW11 TN10 D11
TW12 TN11 D12
TW16 TN12 D6W
(열은 비어 있을 수 있으며 공백이 아닌 탭으로 구분할 수 있습니다. - cas)
BBedit의 Run Unix 명령 기능을 사용하여 이 텍스트를 다음과 같이 변환하고 싶습니다.
'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'
보시다시피, 각 문자열은 작은따옴표로 묶이고 최종 문자열과 구분되며 그 뒤에 쉼표가 옵니다.
미리 감사드립니다.
답변1
입력에 탭으로 구분된 필드가 있는 줄이 있고 먼저 위에서 아래로 각 줄의 첫 번째 필드가 필요하고 두 번째 필드 등이 필요하고 따옴표와 쉼표가 필요하다고 가정하면 다음과 같은 저렴한 솔루션이 있습니다.
최대 9개의 열이 있는 보기 흉한 두 행(sed를 사용하여 형식화됨):
for i in 1 2 3 4 5 6 7 8 9; do cut -f$i file.txt; done |
grep -v '^$' | sed -e "s/^/'/" -e "s/\$/'/" -e '$!s/$/,/'
AWK를 사용한 수동 전치(마지막 쉼표를 제거하기 위해 sed 추가):
awk -F'\t' 'NF > cols {cols=NF}
{for (i=1; i<=NF; i++) { a[i,NR]=$i }}
END { for (j=1;j<=cols;j++) for (i=1;i<=NR;i++)
if (a[j, i] != "") printf "\047%s\047,\n", a[j, i] }' file.txt |
sed -e '$s/,$//'
GNU datamash 사용(및 포맷을 위한 sed):
datamash --no-strict transpose < file.txt | tr -s '\t' '\n' |
sed -e "s/^/'/" -e "s/\$/'/" -e '$!s/$/,/'
(Linux에서 테스트되었으며 처음 두 개는 macOS에서도 작동합니다)
답변2
grep과 sed를 사용해 볼 수도 있습니다.
for i in K TW CM TN CT D ;do grep -ow $i[0-9]*[A-Z]* <input_file;done
각 항목을 작은따옴표로 묶고 각 줄 끝에 쉼표를 추가하려면 위의 내용을 다음 명령에 파이프하세요.
sed "s/$/\'\,/" | sed "s/^/\'/"
답변3
이것이 무엇을 의미하는지 잘 모르겠지만 the Run Unix command feature in BBedit
표시된 입력을 기반으로 표시되는 출력을 생성하기 위해 Unix 명령을 찾고 있다면 awk를 사용하고 필드가 탭으로 구분되어 있다고 가정하십시오.
$ cat tst.awk
BEGIN { FS="\t" }
{
for ( i=1; i<=NF; i++ ) {
if ( $i != "" ) {
a[i,NR] = $i
max_j[i] = NR
}
}
max_i = (max_i > NF ? max_i : NF)
}
END {
for ( i=1; i<=max_i; i++ ) {
for ( j=1; j<=max_j[i]; j++ ) {
printf "%s\047%s\047", sep, a[i,j]
sep = ",\n"
}
}
print ""
}
$ awk -f tst.awk file
'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'
답변4
펄 사용:
$ perl -lne '
# split each input line on single tabs (not one-or-more
# whitespace chars) into temporary array @F.
@F = split /\t/;
# Construct an Array-of-Arrays (AoA) containing the data.
# This works with any number of columns, not limited to 5.
# Assumes each input line has the same number of fields,
# although some may be empty.
foreach my $i (keys @F) {
if (length($F[$i]) > 0) {
push @{$columns[$i]}, "\047" . $F[$i] ."\047" ;
};
};
END {
# flatten the AoA with map and print it
print join(",\n", map { @$_ } @columns);
}' input.txt
'K1',
'K2',
'K3',
'K4',
'K5',
'K6',
'K7',
'K8',
'TW10',
'TW11',
'TW12',
'TW16',
'CM1',
'CM2',
'CM3',
'CM4',
'CM5',
'CM6',
'CM11',
'CM12',
'CM15',
'TN1',
'TN2',
'TN3',
'TN4',
'TN5',
'TN6',
'TN7',
'TN8',
'TN9',
'TN10',
'TN11',
'TN12',
'CT14',
'CT15',
'CT16',
'CT17',
'CT18',
'CT19',
'CT20',
'D01',
'D02',
'D03',
'D04',
'D05',
'D06',
'D07',
'D08',
'D09',
'D11',
'D12',
'D6W'
@columns
이는 입력을 한 줄씩 읽고, 단일 탭 문자를 구분 기호로 사용하여 각 줄을 분할하고, 작은따옴표(8진수)로 묶인 각 줄의 null이 아닌 열에서 호출되는 배열 배열을 구성합니다 \047
.
전체 파일을 읽었을 때 map
"평탄화"(즉, 단일 배열로 변환)를 사용하고 ,\n
각 요소 사이에 인쇄합니다.
그런데, map
목록/배열에 대한 작업을 수행하기 위한 내장 Perl 함수입니다. 특이한 특수 for
루프라고 생각하면 됩니다. perldoc -f map
자세히보다. perldoc -f split
Perl의 기능에 익숙하지 않은 경우에도 split
읽어보면 유용할 것입니다 . 게다가 perldoc -f join
.