임시 파일에 쓰지 않는 sed -i의 대안

임시 파일에 쓰지 않는 sed -i의 대안

"태그"를 제거하고 숫자 등으로 대체하여 템플릿 텍스트 파일을 편집하는 몇 가지 스크립트가 있습니다. 이를 위해 나는 사용합니다

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

입력/출력 상황에 따라 이 작업을 수행하는 더 좋은 방법이 있을 수 있습니다.

관련 정보