Bash 스크립트에서 여러 파일 비교

Bash 스크립트에서 여러 파일 비교

bash와 쉘 프로그래밍은 나에게 새로운 것입니다. 확장자를 가진 파일이 몇 개 있습니다..v.gz, bash 명령에서 일부 작업을 수행하고 결과를 동일한 파일 이름에 저장합니다. . txt확장하다.

예를 들어. txt파일 데이터는 아래와 같습니다. 파일 이름이 다르고 확장자가 동일한 4개의 파일을 고려 중입니다(아마도 30개 이상의 파일이 있을 수도 있음).

file_one.txt

statement_modeule_name_1 
statement_modeule_name_2
statement_modeule_name_3
statement_modeule_name_4
statement_modeule_name_5

data.txt 가져오기

statement_modeule_name_6
statement_modeule_name_7
statement_modeule_name_2
statement_modeule_name_8
statement_modeule_name_9

파일.txt

statement_modeule_name_10
statement_modeule_name_11
statement_modeule_name_6
statement_modeule_name_4
statement_modeule_name_14

data_new.txt

statement_modeule_name_15
statement_modeule_name_16
statement_modeule_name_11
statement_modeule_name_5
statement_modeule_name_17

명령 프롬프트에 예상되는 코드 출력

file_one and Fetch_Data   statement_modeule_name_2

Fetch_Data and one_file   statement_modeule_name_6

file_one and Fetch_Data   statement_modeule_name_4

file_one and Fetch_Data and file4    statement_modeule_name_5

Fetch_Data and Data_new   statement_modeule_name_11

내가하고있는 코드는

for file in *.v.gz;
do
  zgrep -A1 "^module" "$file" | sed -n -e 's/^\(module \)*\(.*(.*)\).*$/\2/p' | cut -f1 -d"(" > $(basename "$file" .v.gz).txt
done     #the result what I get here I mentioned in the question .txt files with data (example)

누구든지 이 작업을 수행하는 데 도움을 줄 수 있습니까? python 또는 bash 스크립트를 사용할 수 있습니다(bash의 경우 python 확장을 제거해야 함).

  • 이제 첫 번째 단계에서 .txt 형식으로 여러 출력 파일을 생성합니다.
  • 이제 여러 .txt 파일을 한 줄씩 비교하고 예상 출력과 같이 파일 이름이 있는 파일에 동일한 줄이 있으면 반환하고 싶습니다.

답변1

$ FILES=( $(find -maxdepth 1 -type f -printf "%P\n") )

$ cat ${FILES[@]} | 
sort |
uniq -d |
xargs -r -d '\n' -I{} bash -c '
  echo $(sed "s/ / and /g" <<<$(grep -xl "{}" '"${FILES[*]}"')), {}'

결과:

file3.txt and file4.txt, modeule_name_11
file1.txt and file2.txt, modeule_name_2
file1.txt and file3.txt, modeule_name_4
file1.txt and file3.txt and file4.txt, modeule_name_5
file2.txt and file3.txt, modeule_name_6

설명하다:

  • FILES=( $(find -maxdepth 1 -type f -printf "%P\n") )- $FILES파일 목록을 보유하는 배열이 됩니다.
  • cat ${FILES[@]}- 파일의 내용을 인쇄합니다.
  • sort | uniq -d- 다른 파일에 나타나지 않는 줄을 확인할 필요가 없으므로 중복된 줄(즉, 둘 이상의 파일에 나타나는 줄)만 표시합니다.
  • xargs -r -d '\n' -I{} bash -c '- 각 라인에 대해 다음 스크립트를 실행합니다. 구분 기호는 새 줄이므로 특수 문자를 지원할 수 있습니다. {}우리가 찾고 있는 라인으로 대체될 것입니다
  • grep -xl "{}" '"${FILES[*]}"'-l- 각 줄에 대해 전체 줄( -x)과 일치하는 파일( )을 인쇄합니다.
  • sed "s/ / and /g" <<<$(grep ... ))- 일치하는 파일 사이의 공백을 다음으로 바꿉니다." 그리고".
  • echo $(...), {}- 일치하는 항목 목록을 인쇄하고 그 뒤에 일치하는 줄( {})을 표시합니다.

답변2

모든 데이터를 하나의 스트림으로 연결하되 각 행 앞에 파일 이름을 붙입니다. 데이터에 탭 문자가 없다고 가정하면 탭 문자를 파일 이름과 원본 데이터 사이의 구분 기호로 사용할 수 있습니다. 그런 다음 데이터는 탭으로 구분된 두 번째 필드로 그룹화되고 파일 이름은 각 그룹에 대해 쉼표로 구분된 목록으로 축소됩니다.

awk -v OFS='\t' '{ print FILENAME, $0 }' *.txt |
datamash --sort groupby 2 collapse 1

주어진 질문의 데이터 출력(예를 들어 필드의 순서를 바꿀 수 있음 datamash cut 2,1):

statement_modeule_name_1        file_one.txt
statement_modeule_name_10       onefile.txt
statement_modeule_name_11       Data_New.txt,onefile.txt
statement_modeule_name_14       onefile.txt
statement_modeule_name_15       Data_New.txt
statement_modeule_name_16       Data_New.txt
statement_modeule_name_17       Data_New.txt
statement_modeule_name_2        Fetch_Data.txt,file_one.txt
statement_modeule_name_3        file_one.txt
statement_modeule_name_4        file_one.txt,onefile.txt
statement_modeule_name_5        Data_New.txt,file_one.txt
statement_modeule_name_6        Fetch_Data.txt,onefile.txt
statement_modeule_name_7        Fetch_Data.txt
statement_modeule_name_8        Fetch_Data.txt
statement_modeule_name_9        Fetch_Data.txt

또는 mlrGNU 대신 Miller( )를 사용하세요 datamash.

awk -v OFS='\t' '{ print FILENAME, $0 }' *.txt | 
mlr --tsv -N nest --ivar , -f 1

질문의 데이터 출력을 제공합니다.

Data_New.txt    statement_modeule_name_15
Data_New.txt    statement_modeule_name_16
Data_New.txt,onefile.txt        statement_modeule_name_11
Data_New.txt,file_one.txt       statement_modeule_name_5
Data_New.txt    statement_modeule_name_17
Fetch_Data.txt,onefile.txt      statement_modeule_name_6
Fetch_Data.txt  statement_modeule_name_7
Fetch_Data.txt,file_one.txt     statement_modeule_name_2
Fetch_Data.txt  statement_modeule_name_8
Fetch_Data.txt  statement_modeule_name_9
file_one.txt    statement_modeule_name_1
file_one.txt    statement_modeule_name_3
file_one.txt,onefile.txt        statement_modeule_name_4
onefile.txt     statement_modeule_name_10
onefile.txt     statement_modeule_name_14

답변3

comm당신의 친구입니다. 두 파일 모두에 대해:

$ comm -12 <(sort file_one.txt) <(sort Fetch_Data.txt)
statement_modeule_name_2

txt현재 디렉터리의 모든 파일에 대해:

for FILE1 in *.txt; do
  for FILE2 in *.txt; do
    [ "$FILE1" == "$FILE2" ] && continue
    echo "$FILE1  $FILE2  $(comm -12 <(sort $FILE1) <(sort $FILE2))"
  done
done

file1ps: 이 솔루션은 and 와 file2나중에 비교하기 때문에 약간 중복됩니다 .file2file1

데이터를 출력합니다:

Data_New.txt  Fetch_Data.txt  
Data_New.txt  file_one.txt  statement_modeule_name_5
Data_New.txt  onefile.txt  statement_modeule_name_11
Fetch_Data.txt  Data_New.txt  
Fetch_Data.txt  file_one.txt  statement_modeule_name_2
Fetch_Data.txt  onefile.txt  statement_modeule_name_6
file_one.txt  Data_New.txt  statement_modeule_name_5
file_one.txt  Fetch_Data.txt  statement_modeule_name_2
file_one.txt  onefile.txt  statement_modeule_name_4
onefile.txt  Data_New.txt  statement_modeule_name_11
onefile.txt  Fetch_Data.txt  statement_modeule_name_6
onefile.txt  file_one.txt  statement_modeule_name_4

comm여기에서 또 다른 주제 에 대해 자세히 알아보세요 .두 파일 사이의 공통 줄

관련 정보