라인을 비교하고 두 개의 다른 파일을 업그레이드하십시오.

라인을 비교하고 두 개의 다른 파일을 업그레이드하십시오.

다음 기능을 가진 여러 텍스트 파일이 있습니다.

$ cat file_1
Line A
Line B
Line C
Line D

$ cat file_2
Line A
Line added 1
Line B
Line D
Line added 2

포함되지 않은 file_1일부 행이 있으며 그 반대의 경우도 마찬가지 입니다 . file_2업그레이드하고 싶어요서로행이 누락되어 둘 다

Line A
Line added 1
Line B
Line C
Line D
Line added 2

이것주문하다of file_1는 유지되지만 file_2put의 적분은 in과 동일한 위치에 있습니다 file_2(머리, 꼬리 또는 무작위 위치가 아님).

1) 적절한 스크립트를 통해 이런 방식으로 파일을 병합할 수 있습니까 bash?

2) 줄 대신에 단락(예: 줄 블록)을 사용할 때 동일한 작업을 수행할 수 있습니까?

답변1

diff file_1 file_2 | grep -Ev '^<|[0-9]+d[0-9]+' | patch file_1

답변2

1) 적절한 bash 스크립트를 통해 이런 방식으로 파일을 병합할 수 있습니까?

다른 논평자들이 말했듯이 추가/이동/삭제를 구별하는 것은 정확하지 않으며 에 맡기는 것이 가장 좋습니다 diff. 그러나 "원본" 줄이 고유하고 두 파일에서 동일한 순서로 표시된다는 제한으로 인해 더 간단합니다.

#!/bin/bash

#build list of common lines
grep -Fxf file_2 file_1 > common

#optional: confirm that they appear in the same order in both files
grep -Fxf file_1 file_2 > common2
if ! diff -q common common2 ; then
    echo "Duplicate or rearranged common lines, can't merge" >&2
    exit 1
fi

#copy lines from input until one is found that matches the argument
function copy_till () {
    while read l && [ "$l" != "$1" ] ; do
            printf "%s\n" "$l"
    done
}

# open both files, for parallel reading
exec 3< file_1
exec 4< file_2

#for each line in the common file
while read line ; do
    # copy any lines that were inserted before it, for each input file
    copy_till "$line" <&3
    copy_till "$line" <&4
    # and the original line
    printf "%s\n" "$line"
done < common > merged

# any trailing lines, after the last common line
cat <&3 >> merged
cat <&4 >> merged

2) 줄 대신에 단락(예: 줄 블록)을 사용할 때 동일한 작업을 수행할 수 있습니까?

줄에 대해 이 작업을 수행하는 방법을 찾으면 sed단락을 긴 줄로 변환하고(줄 바꿈을 다른 임시 표시로 저장) 다시 변환할 수 있습니다. 주석 스크립트에서 많이 차용함https://unix.stackexchange.com/a/219562/90751:

sed '/^$/!{H;$ba;d};:a;x;s/\n/\\n/gp;d' -i.bak file_1
sed '/^$/!{H;$ba;d};:a;x;s/\n/\\n/gp;d' -i.bak file_2
merge.sh # or whatever you called the answer to part 1)
sed 's/\\n/\n/g' merged > merged.paras

mv file_1.bak file_1
mv file_2.bak file_2

이 문자열이 \n단락에 나타나면 다른 문자열을 줄바꿈으로 사용하세요.

답변3

1) 적절한 bash 스크립트를 통해 이런 방식으로 파일을 병합할 수 있습니까?

만약에:

  • file_2기본적으로 file_1추가 및 삭제된 라인하지만 움직임은 없어, 그리고
  • 두 파일 모두 탭 문자를 포함하지 않습니다.

GNU는 diff간단한 솔루션의 핵심을 제공합니다.

#!/usr/bin/env bash
diff -y "$1" "$2" | while IFS=$'\t' read s1 s2 s3; do
  if [[ $s1 == *\> ]]; then
    # New line from second file
    echo "$s2"
  else
    case "$s2" in
      *\|) # Changed line, so...
        echo "$s1"
        echo "$s3"
      ;;
      *) # Output first file
        echo "$s1"
      ;;
    esac
  fi
done

이렇게 하면 원하는 것은 무엇이든 할 수 있는 표준 출력으로 통합된 출력이 전송됩니다. 맹목적으로 file_1합계를 덮어쓰는 것보다 먼저 출력을 확인하는 것이 좋습니다 file_2.

(이것이 어떻게 작동하는지 궁금하다면 실행하여 diff -y file_1 file_2 | cat -A실제로 출력 내용을 확인하세요 diff.)

2) 줄 대신에 단락(예: 줄 블록)을 사용할 때 동일한 작업을 수행할 수 있습니까?

예. 기본적인 로직은 위와 동일하지만 먼저단락을 한 줄로 변환위의 입력으로 형식이 변경된 텍스트를 사용합니다 diff. 그런 다음 두 가지 출력 옵션이 있습니다.

  • 원래 단락을 유지합니다.올바른 파일에서 각 단락을 읽고 출력하십시오. 이것은 당신을 위한 연습입니다.
  • 새 단락을 생성합니다.echo위의 각 스크립트는 echo ... | fmt -w<desire_line_width>.

답변4

이는 본질적으로 실행에 관한 문제입니다.2가지 방법또는양방향 병합두 파일 간의 차이점을 동기화합니다. 내 사용 사례는 GitHub 저장소에서 업그레이드를 수행하고 업그레이드할 때마다 키를 다시 입력하지 못하도록 변수 파일에 고유 데이터를 유지하는 것입니다!

먼저 확인을 위해 결과를 다시 생성할 수 있도록 사용된 표현식과 테스트 데이터를 보여드리겠습니다(데이터 세트의 필드 구분 기호를 "="에서 공백 ""으로 변경하세요.):

 paste -d'\n' file1.txt file2.txt|awk -F'=' '!seen[$1]++' > file3.txt

내 테스트 데이터는 다음과 같습니다.

파일 1.txt:

LineA='value1'
LineB='value2'
LineC='value3'
LineD='value4'
#
LineE='value5'
LineF='value6'
#
LineG='value7'
#
LineH='value8'

파일 2.txt:

LineA=''
LineB=''
NEWVARIABLE1='This only Exists in file2.txt Under LineB'
LineC=''
LineD=''
#
LineE=''
NEWVARIABLE2='This only Exists in file2.txt Under LineE'
LineF=''
#
LineG=''
#
LineH=''
NEWVARIABLE3='This only Exists in file2.txt under LineH'

산출:

paste -d'\n' file1.txt file2.txt|awk -F'=' '!seen[$1]++' > file3.txt

콤비네이션파일 3.txt다음과 같습니다.

LineA='value1'
LineB='value2'
LineC='value3'
NEWVARIABLE1='This only Exists in file2.txt Under LineB'
LineD='value4'
#
LineE='value5'
LineF='value6'
NEWVARIABLE2='This only Exists in file2.txt Under LineE'
LineG='value7'
LineH='value8'

NEWVARIABLE3='This only Exists in file2.txt under LineH'

문서에 표시2.txt를 제외한 모든 값은 비어 있습니다('').새로운 변수 x가치. 출력을 보면 파일의 모든 고유 데이터를 볼 수 있습니다.1병합된 .txt가 유지되었습니다.

또한 file2.txt("업데이트된" 파일)에 추가된 각각의 새로운 "변수"는 병합된 file3.txt를 한 줄씩 줄입니다. 따라서 file2.txt에 4개의 새 변수를 추가하면 네 번째 새 변수는 결합된 file3.txt에서 file3.txt 아래 4줄이 됩니다. 그러나 이것은 내 사용 사례에서는 문제가 되지 않습니다.

불행히도 이것은 첫 번째 사용 사례에서 작동합니다.양방향 파일 병합. 그러나 연속적인 테스트 블록을 file2.txt(다시 "업데이트된 파일")에 추가하면 이러한 테스트 블록은 파일의 주변 줄과 인터리브됩니다.1병합된 파일의 .txt. TXT. 그래서 나는 당신을 위해 절반을 해결했지만 내 사용 사례는 질문의 첫 번째 부분과만 겹칩니다.

저는 이 포럼과 다른 포럼의 다른 포스터에서 다양한 솔루션을 시도했지만 실제로 이것이 효과를 발휘하는 유일한 솔루션입니다. HTH-

관련 정보