이 내 꺼야 file1
:
#$BQ #{ 볼륨@홈 } #데이터베이스바 #relationshiptcdeatid #복사 1 #{버전 0} #opendb #분명한 #.루노 := 72 #.infno := 1 #.tid.noel := 101 #.tid.info := 64 #.tid.setnr := 1225 <---(1225 번호가 변경됩니다) #.typeidm := 1 #.소스 테이블:= 2 #writedb #분명한 #.루노 := 72 #.infno := 205 #.tid.noel := 101 #.tid.info := 76 #.tid.setnr := 5625 <---(5625 번호가 변경됩니다) #.typeidm := 1 #.소스 테이블:= 2 #writedb #$EOJ
file2
올바른 항목이 있습니다 .
#.tid.info := 3345 <---(이 번호를 입력하고 싶습니다.파일 164 대신) #.tid.setnr := 1254 <---(이 번호를 입력하고 싶습니다.파일 11225 대신) #.tid.info := 5567 <---(이 번호를 입력하고 싶습니다.파일 176 대신) #.tid.setnr := 9056 <---(이 번호를 입력하고 싶습니다.파일 15625 대신)
file1
에서 나오는 데이터를 기반으로 변경하고 싶습니다 file2
.
나는 열심히 노력했다
sed "s/tid.setnr := 1225/tid.setnr := 1254/g" file1 > modified_file1
하지만 이 작업을 수동으로 수행하고 싶지는 않습니다. 스크립트에서 새 값과 값을 읽고 수정 tid.info
하도록 tid.setnr
하고 file2
싶습니다 file1
. file2
에는 , 등등이 포함되어 있습니다.file1
tid.info
file2
file1
tid.setnr
답변1
GNU sed R 명령을 사용하십시오.
sed -e 's/^#.tid.setnr :=.*//;tA;b;:A;R file2' -e 'd' file1
답변2
이를 수행하는 한 가지 방법 은 스크립트를 sed
생성하는 것입니다 .sed
tmpfile=/tmp/Nainita.$$
exec 3< file2
grep -n "tid\.setnr" file1 | while IFS=: read n junk
do
IFS= read -r line <&3 || break
printf "%sc%s\n%s\n" "$n" '\' "$line"
done > "$tmpfile"
exec 3<&-
sed -f "$tmpfile" file1 > modified_file1
rm -f "$tmpfile"
exec 3< file2
file2
파일 설명자를 읽기 위해 엽니다 . 3.- 줄 번호별로 다음을 포함하는 줄을 찾습니다
grep -n
. 이것은 루프에 공급됩니다.file1
tid.setnr
while
while IFS=: read n junk
while … read …
한 번에 한 줄씩 읽는 것을 의미하며, 읽을 정보가 있는 한 반복합니다(즉, 데이터 끝에 도달하면 중지).IFS=: read n junk
:
첫 번째 행(즉, 원본 행 번호 )grep -n
이전의 모든 항목을 읽고n
나머지 행(이전 데이터 행)tid.setnr
을 읽는다는 의미입니다junk
. 이는 신경 쓰지 않기 때문에 무시합니다.
IFS= read -r line <&3
파일 설명자 3( )에서 한 줄을 읽고file2
, 쉘이 이를 손상시키지 않도록 지시하는 방법을 모두 수행한 다음 이름이 지정된 변수에 넣습니다line
.… || break
위의 작업이read
실패하면(아마도 파일 끝으로 인해) 루프를 중단하세요.- 썼다
printf
sed
씨hange 명령은 행 번호를 가리키며 , 이는 해당 행이 변수의 내용n
으로 대체되어야 함을 나타냅니다 .line
done > "$tmpfile"
루프의 끝을 표시while
하고 전체 루프의 표준 출력이 임을 지정합니다$tmpfile
. 결과는 다음과 같습니다.13c\ #.tid.setnr := 1254 22시\ #.tid.setnr := 9056
while
두 입력 중 하나에서 EOF를 얻으면 루프가 종료됩니다 . 따라서 행보다 더 많은 행이 있으면file1
추가 행은 변경되지 않은 채로 유지됩니다(즉, 해당 명령이 생성되지 않습니다). 마찬가지로, 보다 많은 행이 있는 경우 추가 행은 무시됩니다. 불행하게도 이 기능을 추가하는 것은 어렵지 않지만 이 차이점은 보고되지 않습니다.tid.setnr
file2
c
file2
tid.setnr
file1
exec 3<&-
파일 설명자를 닫습니다 3.sed -f "$tmpfile" file1 > modified_file1
sed
에서 실행file1
하고 에서 명령을 읽고$tmpfile
출력을 씁니다modified_file1
.
원하는 대로 작동해야 합니다. 물론 원하는 경우 파일 이름을 변경할 수 있습니다. "있는 그대로" 한 번 실행한 다음 파일을 살펴보고 modified_file1
(또는 출력을 리디렉션하지 않도록 명령을 변경하여 sed
화면에 기록) 출력이 원하는 것인지 확인해야 합니다. 그런 다음 원하는 경우 해당 위치에서 편집 sed
하도록 명령을 변경할 수 있습니다 .sed -i
file1
sed
명령에서 "줄 번호가 너무 많습니다"와 같은 오류가 발생 하면 $tmpfile
스크립트 파일( )을 더 작은 파일로 분할해 보십시오. 각 명령은 두 줄이므로 100개 미만의 명령 크기로 시작하는 것이 좋습니다. 예를 들어 90개 명령 또는 180개 줄입니다. 텍스트 편집기1 를 사용하여 이 작업을 수동으로 수행할 수 있지만 이 작업을 위해 특별히 작성된 도구가 있습니다. 직관적으로 split
.command 라고 합니다.
split --lines=180 "$tmpfile"
xaa
스크립트는 현재 디렉터리에서 , xab
, , ...라는 xac
파일 로 분할됩니다 . 첫 번째N−1의 길이는 180줄입니다. 마지막 항목은 전체를 구성하는 데 필요한 모든 항목입니다(≤ 180). 예를 들어, 500개의 인스턴스가 있는 경우 tid.setnr
스크립트 길이는 1000줄이 되고 6개의 x
파일(
xaa
, xab
, xac
, xad
) 이 xae
각각 180줄로 구성되어 xaf
100줄이 됩니다. 지금 그것을 할
sed -f xaa file1 > modified_file1aa
여전히 '행이 너무 많습니다'라는 메시지가 표시되면 돌아가서 행 수를 줄여 다시 시도해 보세요 --lines
. 오류가 보고되지 않으면 modified_file1aa
처음 90줄이 tid.setnr
변경되었는지 확인하세요. 괜찮아 보이면 그렇게 하세요
sed -f xab modified_file1aa > modified_file1ab
sed -f xac modified_file1ab > modified_file1ac
sed -f xad modified_file1ac > modified_file1ad
sed -f xae modified_file1ad > modified_file1ae
sed -f xaf modified_file1ae > modified_file1af
modified_file1af
이제 마지막이에요 modified_file1
.
실험 하고 싶다면 다음을 수행할 수 있습니다.
--lines
최대값이 무엇인지 찾을 때까지 더 큰 숫자를 시도해 보십시오 .노력하다
sed -f xaa -f xab -f xac -f xad -f xae -f xaf file1 > modified_file1_test
그러나 이것은 작동하지 않을 수 있습니다.
- 위의 실험을 하시면 결과를 알려주시기 바랍니다.
이 작업을 한 번만 수행하면 완료된 것입니다. 하지만 이 작업을 반복적으로 수행해야 하는 경우 이 답변 상단에 있는 코드 블록의 마지막 두 줄을 다음으로 변경하세요.
분할 --lines=180 "$tmpfile" <--- (물론 자신에게 맞는 숫자를 사용하세요) cp file1 수정된 파일 1 f의 경우 x* 하다 sed -i -f "$f" 수정된_file1 완벽한 rm -f "$tmpfile" x*
앞서 언급했듯이 이 -i
옵션은 sed
지정된 파일을 그 자리에서 편집하도록 지시합니다(즉, 변경 사항을 입력 파일에 다시 기록). 아니면 더 간단하게,
split --lines=180 "$tmpfile"
for f in x*
do
sed -i -f "$f" file1
done
rm -f "$tmpfile" x*
원본을 그대로 유지할 필요가 없는 경우 file1
.
사용법 요약은 다음과 같습니다 split
.
나뉘다 [옵션]……[입력하다[접두사]]
기본 동작은 PREFIXaa
, 등이라는 이름의 파일을 생성하는 것입니다 PREFIXab
. PREFIXac
즉, 기본값PREFIX
예 x
. 이름이 로 시작하는 다른 파일이 있는 경우 유일한 파일(예: 또는 )로 x
정의한 다음 위의 내용을 다음으로 변경 해야 합니다.prefix
prefix=Nainita.$$.
prefix=/tmp/Nainita.$$.
split --lines=180 "$tmpfile" "$prefix"
for f in "$prefix"*
do
sed -i -f "$f" file1
done
rm -f "$tmpfile" "$prefix"*
______
1 처벌을 좋아한다면,할 수 있다그렇게 하세요 sed
– 그런데 왜 불장난을 합니까?
답변3
{ sed '/^#\.tid\.setnr/!d;=;g;G' |
paste -d'c\\\n' - - - ./addfile
} <./mainfile | sed -f - ./mainfile
관련 줄 번호 앞에만 추가됩니다../메인 파일각 라인에. /파일 추가명령 문자열 c\
과<줄 바꿈>편집을 위해 결과를 sed
다른 스크립트에 스크립트로 전달하기 전에./메인 파일. 샘플 데이터를 기반으로 생성된 스크립트는 다음과 같습니다.
13c\
#.tid.setnr := 1254 <--- (I want to put this number in file1 in place of 1225)
22c\
#.tid.setnr := 9056 <--- (I want to put this number in file1 in place of 5625)
... sed
매달린 c
선을 나타냅니다.13그리고스물 둘각 명령과 일치하는 추가 행을 출력합니다.
답변4
펄을 발견했습니다. 이 스크립트는 트릭을 수행하는 것처럼 보이는 대략적인 스크립트입니다.
#!/usr/bin/perl
#
use strict;
# subroutine to load a test file into an array
sub load{
my $file = shift;
open my $in, "<", $file or die "unable to open $file : $!";
my @data = <$in>;
chomp @data;
foreach (@data) { s/\cM//g;}
return @data;
}
my $file1 = shift || die "usage: $0 [file1] [file2]\n";
my @file1_data = &load($file1);
my $file2 = shift || die "usage: $0 [file1] [file2]\n";
my @file2_data = &load($file2);
my $i = 0;
foreach( @file1_data )
{
if( $i < @file2_data )
{
my @s = split / /, $file2_data[$i];
if( @s )
{
if( /^$s[0]/ )
{
$_ = $file2_data[$i++];
}
}
}
print "$_\n";