"태그"를 제거하고 숫자 등으로 대체하여 템플릿 텍스트 파일을 편집하는 몇 가지 스크립트가 있습니다. 이를 위해 나는 사용합니다
sed -i
주문하다. 그러나 스크립트가 실행되는 서버에서 쓰기/읽기 시간 문제가 발생하여 sed -i 명령이 실행될 때마다 디스크에 임시 파일을 쓰기 때문에 스크립트를 실행하는 데 오랜 시간이 걸립니다.
교체할 때마다 디스크에 임시 파일을 쓰지 않는 다른 방법이 있습니까? 텍스트 파일을 메모리에서 편집하고 모든 대체가 수행된 후에만 쓸 수 있습니까? 아니면 동일한 sed 명령에 여러 대체 항목을 쌓을 수 있습니까?
명확히 하기 위해 스크립트의 형식은 다음과 같습니다.
input=shiftLeft.txt
while IFS= read -r line
do
sed -i "s/install, element = $line, at=/install, element = $line, at= -0.001 +/g" processedFiles/layoutDB.seq
done < "$input"
즉, 하나의 텍스트 파일에서 값을 읽은 다음 해당 값을 기반으로 다른 텍스트 파일에서 일부 변경을 수행합니다. 많은 수의 값에 대해 이를 반복합니다.
답변1
문제는 sed -i
많은 임시 파일이 생성되는 것이 아니라 동일한 입력 파일로 여러 번 실행하고 각 파일이 다음과 같이 출력을 위한 임시 파일을 생성한다는 것입니다 strace
.
execve("/bin/sed", ["sed", "-i", "-e", "", "/tmp/foo"], 0x7fff10da5288 /* 36 vars */) = 0
openat(AT_FDCWD, "/tmp/foo", O_RDONLY) = 3
openat(AT_FDCWD, "/tmp/sedVdjaBk", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("/tmp/sedVdjaBk", "/tmp/foo") = 0
+++ exited with 0 +++
해결책은 sed -i
한 번만 실행하는 것입니다.
이를 수행하려면 먼저 sed
입력 파일을 sed
프로그램으로 변환하는 명령을 작성하십시오. 그것은 다음과 같습니다:
sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!"
(예를 들어 입력 파일에 유효한 정규식 문자가 포함된 경우 이를 개선할 수 있지만 s/install, element = &, at=/\& -0.001 +/g
이는 이 질문의 범위를 벗어납니다.)
이를 테스트하여 생성된 스크립트에 만족하는지 확인하세요.
sed
그런 다음 변환된 텍스트를 프로그램 파일로 사용하려면 또 다른 것이 필요합니다 . 표준 입력에서 읽도록 프로그램에 지시하여 이를 수행할 수 있습니다(다른 옵션도 있지만).
sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' \
shiftLeft.txt |
sed -f - -i processedFiles/layoutDB.seq
-i
원하는 효과가 만족스러울 때까지 플래그 없이 다시 테스트하세요 .
¹ 우리가 사용하고 있기 때문에세게 때리다, 절차적 대체를 사용할 수 있습니다.
sed -f <(sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' shiftLeft.txt) \
-i processedFiles/layoutDB.seq
표준 셸에서는 변환된 텍스트를 문자열로 캡처하여 명령줄 스크립트로 제공해야 합니다.
sed -e "$(sed -e 's!.*!s/install, element = &, at=/install, element = &, at= -0.001 +/g!' shiftLeft.txt)" \
-i processedFiles/layoutDB.seq
답변2
쉘 루프에서 sed를 반복적으로 호출하는 대신 awk를 한 번만 호출하십시오. 예를 들어 (테스트할 샘플 입력/출력을 제공하지 않았기 때문에 테스트되지 않았습니다) "내부" 편집을 위해 GNU awk를 사용하고 match( ) :
awk -i inplace '
NR==FNR { lines[$0] }
(FNR>NR) && match($0,/(.*install, element = )([^,]+)(, at=)/,a) && (a[2] in lines) {
$0 = a[0] " -0.001 +"
}
{ print }
' shiftLeft.txt processedFiles/layoutDB.seq
입력/출력 상황에 따라 이 작업을 수행하는 더 좋은 방법이 있을 수 있습니다.