외부 공급업체에서 *.csv 파일 형식으로 20개가 넘는 테이블의 데이터 덤프를 제공했습니다. 문서가 부족하기 때문에 RDBMS 의미에서 "관련"된 파일을 찾으려면 파일을 수동으로 탐색해야 합니다. 어떤 파일이 동일한 문자열 패턴을 가지고 있는지 찾아 깔끔하게 인쇄할 수 있는 방법이 있나요?
현재 저는 이 작업을 수행하고 수동으로 연결하고 있습니다.
$> head -n 1 *.csv
이것은 나에게 다음과 비슷한 결과를 제공합니다
==> EVO_ANGLE.csv <==
"evo_ang_id","angle_description"
==> EVOP_IMAGE.csv <==
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path", "image_type"
==> IMAGE_TYPE.csv <==
"id","image_type","group","description"
보시다시피 파일 EVO_ANGLE
과 은 서로 관련되어 EVOP_IMAGE
있고 공통점 이 있습니다 .evo_ang_id
EVOP_IMAGE
IMAGE_TYPE
image_type
이 정보를 인쇄하는 더 좋은 방법이 있습니까? 각 파일에 대해 해당 필드가 있는 다른 파일을 어디에서 확인할 수 있습니까?
이에 대한 최선의 해결책은 다음을 순서대로 수행하는 쉘 스크립트를 작성하는 것입니다.
- 각 파일의 첫 번째 줄을 가져와 배열의 맵에 저장합니다.
- 각 줄의 각 단어에 대해 배열에서 해당 단어가 나타나는 위치를 찾습니다.
- 이 정보를 모아서 인쇄하십시오.
이는 번거로운 일이며 제대로 작동하려면 많은 디버깅이 필요하며 콘솔 출력을 보는 것이 더 빠를 수도 있습니다. 더 좋은 방법이 있나요? Cut/Join/Grep 조합에 대한 팁이 있습니까?
답변1
특정 속성이 속한 파일을 찾고 있다면 를 사용할 수 있습니다 awk
.
csv
파일이 다음과 같다고 가정합니다 .
$ for i in *.csv; do echo $i; head -n1 $i; echo; done
EVO_ANGLE.csv
"evo_ang_id","angle_description"
EVOP_IMAGE.csv
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path", "image_type"
IMAGE_TYPE.csv
"id","image_type","group","description"
다음 awk
명령은 속성과 파일 이름을 반대로 바꿉니다.
$ awk -F', *' ' # field separator = comma and optional spaces
FNR==1{ # Parse only the first line of each file.
for(i=1;i<=NF;i++) # Loop through all fields, and store them
a[$i]=a[$i] " " FILENAME # in an array together with the filename.
}
END{ # When all files parsed,
for(i in a) print i,a[i] # print the content of the array
}' *.csv
"image_name" EVOP_IMAGE.csv
"evo_collection" EVOP_IMAGE.csv
"image_path" EVOP_IMAGE.csv
"file_format" EVOP_IMAGE.csv
"image_type" EVOP_IMAGE.csv IMAGE_TYPE.csv
"evop_id" EVOP_IMAGE.csv
"evop_image_id" EVOP_IMAGE.csv
"id" IMAGE_TYPE.csv
"evo_ang_id" EVO_ANGLE.csv EVOP_IMAGE.csv
"description" IMAGE_TYPE.csv
"group" IMAGE_TYPE.csv
"angle_description" EVO_ANGLE.csv
여러 파일에 속하는 속성을 필터링해야 하는 경우 다음 명령을 사용하면 됩니다.
$ awk -F', *' 'FNR==1{for(i=1;i<=NF;i++) a[$i]=a[$i] " " FILENAME}END{for(i in a) print i,a[i]}' *.csv | awk 'NF>2'
"image_type" EVOP_IMAGE.csv IMAGE_TYPE.csv
"evo_ang_id" EVO_ANGLE.csv EVOP_IMAGE.csv
답변2
이것은 bash 중심 버전과 매우 비슷해 보입니다.올리브의 awk 버전
unset fileheads fields
declare -A fileheads
declare -A fields
for f in *.csv
do
IFS=, fileheads[$f]=$(head -n1 "$f");
set -f
for field in ${fileheads[$f]}
do
fields[$field]+=x
done
set +f
done
for field in ${!fields[*]}
do
[[ ${#fields[$field]} -gt 1 ]] || continue
for file in ${!fileheads[*]}
do
[[ ${fileheads[$file]} =~ $field ]] && echo "$file has $field"
done
echo
done
이는 각 파일(라인 1)의 필드를 fileheads
파일 이름별로 색인이 지정된 연관 배열로 수집합니다. 또한 각 필드 이름의 발생 횟수 목록을 수집합니다. 여기서는 필드 이름 자체에 쉼표가 나타나지 않는다고 가정합니다.
그런 다음 알려진 모든 필드를 반복합니다. 그 중 하나라도 여러 번 표시되면 파일(배열의 인덱스 fileheads
)을 반복하여 해당 필드가 포함되어 있는지 확인합니다. 가독성을 위해 최소한 두 개의 파일이 이 기준을 충족해야 하며 해당 파일 이름과 링크 필드가 에코되고 그 뒤에 빈 줄이 표시됩니다.
실행 예시:
입력하다
$ head -n1 *.csv
==> EVOP_IMAGE.csv <==
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path","image_type"
==> EVO_ANGLE.csv <==
"evo_ang_id","angle_description"
==> IMAGE_TYPE.csv <==
"id","image_type","group","description"
산출
EVOP_IMAGE.csv has "evo_ang_id"
EVO_ANGLE.csv has "evo_ang_id"
EVOP_IMAGE.csv has "image_type"
IMAGE_TYPE.csv has "image_type"