견본
wolf@linux:~$ cat data.csv
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
C,1.1.1.1,1.1.1.1,1.1.1.1,1.1.1.1,1.1.1.1
D,2.2.2.1,2.2.2.1,2.2.2.2,2.2.2.3,2.2.2.4
wolf@linux:~$
이 샘플에는 일부 중복된 데이터가 있습니다. 예를 들어 3.3.3.3
A행과 B행에 2개가 있습니다.
wolf@linux:~$ egrep 3.3.3.3 data.csv
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
wolf@linux:~$
이제 A,B,C,D
첫 번째 열과 관련 데이터에만 관심이 있습니다.
제가 찾아야 할 4가지 데이터는 다음과 같습니다.
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5
그래서 나는 egrep에서 |
and를 사용합니다.-o
wolf@linux:~$ egrep '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
D,2.2.2.1,2.2.2.1,2.2.2.2,2.2.2.3,2.2.2.4
wolf@linux:~$
출력은 양호하지만 데이터가 너무 많습니다. 관련 데이터와 첫 번째 열만 원합니다.
그럼 여기 또 다른 시도가 있습니다-o
wolf@linux:~$ egrep -o '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv
4.4.4.4
3.3.3.3
3,3.3.3
2.2.2.3
wolf@linux:~$
이제 문제는 첫 번째 열( A/B/C/D
) 을 가져올 수 없다는 것입니다.
다음에 시도해 보세요
wolf@linux:~$ egrep '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv | cut -d , -f 1
A
B
D
wolf@linux:~$
첫 번째 열은 얻었지만 데이터는 얻지 못했습니다. 출력을 보면 A
둘 다 무엇을 나타내는지 3.3.3.3
, 4.4.4.4
출력에 표시되지 않기 때문에 알 수 없습니다.
이것은 실제로 내가 원하는 결과가 아닙니다. 지금 내가 생각하는 건 이거야
원하는 출력
입력하다
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5
산출
D 2.2.2.3
A,B 3.3.3.3
A 4.4.4.4
- 5.5.5.5
불행히도 지금은 해결책이 생각나지 않습니다. 도와주세요
답변1
$ cat script.awk
NR == FNR {
a[$0]
next
}
{
for (i = 2; i <= NF; i++) {
for (k in a) {
if ($i == k) {
a[k] = a[k] ? a[k] "," $1 : $1
}
}
}
}
END {
for (k in a) {
print a[k] "\t" k
}
}
다음과 같이 실행하세요:
$ cat search.txt
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5
$ awk -F, -f script.awk search.txt data.csv
A,B 3.3.3.3
D 2.2.2.3
A 4.4.4.4
5.5.5.5
답변2
먼저 정규식은 2.2.2.3
일치할 뿐만 아니라(모든 문자와 일치하는 정규식 연산자와 마찬가지로) 내부적으로도 일치합니다.2.2.2.3
212.243
.
22.2.2.36
여기서는 다음을 사용합니다 perl
.
<data.csv perl -F, -lane '
BEGIN {for (@l = qw{2.2.2.3 3.3.3.3 4.4.4.4 5.5.5.5}) {$v{$_} = []}}
for (grep $v{$_}, @F[1..$#F]) {push @{$v{$_}}, $F[0]}
END {for (@l) {print(join(",", @{$v{$_}}) || "-", "\t$_")}}'
이것은 만든다:
D 2.2.2.3
A,B 3.3.3.3
A 4.4.4.4
- 5.5.5.5
항목의 질문에 대답하려면 grep -o
( -o
btw, 비표준 확장으로) 출력 행에서 입력 행의 여러 부분을 보고하려면 다음을 사용할 수 있습니다 pcregrep
.
<data.csv pcregrep -o1 -o2 --om-separator=$'\t' \
'^([^,]*).*?,(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)(,|$)'
그러나 이는 한 줄에 한 단어만 보고합니다. 여기에 주어진:
A 4.4.4.4
B 3.3.3.3
D 2.2.2.3
을 사용하여 Perl과 같은 정규식 지원(BTW, 대부분의 구현에서 PCRE는 Perl과 같은 정규식 일치에 사용되므로 와 동일)으로 빌드한다고 grep -Po
가정하면 다음을 수행할 수 있습니다.grep
pcregrep -o
$ grep -Po '^[^,]*+(?=.*?(?1))|((?<![^,])(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)(?![^,]))' data.csv
A
4.4.4.4
3.3.3.3
B
3.3.3.3
D
2.2.2.3
이것은 first-field-provided-there-is-matching-data|matching-data
.
이는 전방 예측 연산자를 사용하여 구현 provided-there-is-matching-data
됩니다 .(?=...)
전제는 다음 내용이 일치한다는 것입니다....
, 여기서 (?1)
정규식은 첫 번째 캡처링 그룹에 저장되므로 일치하는 데이터 뒤에는 임의 개수의 문자( .*?
)가 옵니다.
(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)
일치하는 데이터의 경우 이스케이프를 위해 s를 사용 .
하지만 다음을 나타내기 위해 일부 부정 탐색 연산자( (?<!...)
및 (?!...)
)를 사용합니다.전제는 전후의 내용이아니요캐릭터 이외의 캐릭터,
csv 필드의 내용과 정확히 일치하는지 확인하세요.
답변3
이를 수행하는 간단한 방법은 다음과 같습니다. 찾을 키는 key.txt라는 파일에 한 줄에 하나씩 나열되며 검색할 데이터가 인수로 배치되는 perl 명령의 표준 입력에 배치됩니다.
$ < keys.txt \
perl -F, -lane '
$.==1 && chomp(@keys = <STDIN>);
$_ .= "$F[0]," for @h{
grep { my $k = $_; grep(($_ eq $k), @F)} @keys;
}}{$, = "\t";
print((($h{$_} //= "-") =~ s/,$//r), $_) for @keys;
' data.csv
D 2.2.2.3
A,B 3.3.3.3
A 4.4.4.4
- 5.5.5.5
답변4
밀러 사용(https://github.com/johnkerl/miller) 그리고 실행
mlr --c2t -N reshape -r "^[^1]$" -o item,value \
then filter '$value=~"(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)"' \
then cut -x -f item \
then nest --implode --values --across-records -f 1 --nested-fs "," \
then reorder -f value data.csv >output
당신은 할 것
4.4.4.4 A
3.3.3.3 A,B
2.2.2.3 D
그런 다음 필터 목록을 사용하십시오.
$ cat list
8.8.8.8
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5
넌 달릴 수 있어
mlr --tsv -N join --ul -j 1 -f list then unsparsify output
가지다
4.4.4.4 A
3.3.3.3 A,B
2.2.2.3 D
8.8.8.8
5.5.5.5