텍스트 블록에 행을 추가하여 이전 행의 값을 증가시킵니다.

텍스트 블록에 행을 추가하여 이전 행의 값을 증가시킵니다.

다음 내용이 포함된 텍스트 파일 이름이 있습니다 class.txt.

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=SECOND
whitelist.2=THIRD
whitelist.3=FOURTH

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

블록 중 하나에 새 행을 추가하고 싶다고 가정해 보겠습니다. 예를 들어 블록 SAMPLE에 새 항목이 있으면 새 항목이 추가되면 숫자가 자동으로 증가해야 합니다. 원하는 출력LETTERwhitelist

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=OLD
whitelist.2=NEW
whitelist.3=FOURTH
whitelist.4=SAMPLE

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

이를 수행할 수 있는 방법이 있습니까 sed?

답변1

Ralph의 답변에 대한 내 의견에서 말했듯이 이 작업에는 더 나은 도구가 있습니다. 예를 들어 awk단락 모드를 사용 whitelist.0=SAMPLE하고 블록이 비어 있으면 추가하고 그렇지 않으면 추출하지 않을 수 있습니다. 마지막 필드(이 경우 행)에서 시작하여 whitelist.NR+1=SAMPLE블록에 추가합니다.

awk -vRS= -vORS='\n\n' 'BEGIN{z="whitelist.0=SAMPLE";FS="\n"}
/LETTER/{if (/[0-9]=/){split($NF, a, /[.=]/);sub(/0/, a[2]+1, z)}
sub (/$/,"\n"z ,$0)};1' infile

답변2

엄청난! 이제 나는 새로운 것을 배웠습니다. 나는 sed다양한 (사소한) 대체를 사용했지만 실제로 프로그래밍할 수 있다는 것을 깨닫지 못했습니다. 분명히 이것은 레지스터가 두 개뿐이고 언어가 매우 모호했기 때문에 다소 약한 "기계"였습니다.

입력 변수를 허용하지 않기 때문에 명령줄에서 BLOCK과 ENTRY를 실제 토큰으로 대체하여 준비된 동적 프로시저를 사용하여 호출되는 스크립트 sed로 설정했습니다 . 교체는 항목 삽입을 구현하기 위한 특정 프로그램을 준비하기 위해 별도의 단순 교체로 수행 됩니다.shsedsed

아래 스크립트가 해당 작업을 수행하는 것 같습니다. 호출되면 addentry다음과 같이 호출됩니다.

$ addentry LETTER SAMPLE < data

입력 데이터를 재생산하고 삽입된 항목을 출력으로 갖습니다. 필요한 경우 "제자리에서 편집" -i할 수 있는 옵션이 있다고 가정합니다 sed.

#!/bin/sh

/bin/sed -n "$(cat << EOF | sed -e "s/BLOCK/$1/g;s/ENTRY/$2/g"
# Initialize hold space with 0
1 { x ; /^$/ s/^$/0/; x }

# Lines outside the interesting block are just printed
/\s*serverClass:BLOCK/,/^$/! { p }

# Lines of the interesting block are considered more in detail
/\s*serverClass:BLOCK/,/^$/ {

  # The final empty line is replaced by the new entry, using the line
  # counter from the "hold buffer"
  /^$/ { g; s/\(.*\)/whitelist.\1=ENTRY/p; s/.*//p; b xx }

  # print the line
  p

  # Jump forward for the block leader (note xx is a label)
  /serverClass:/ { b xx }

  # Increment hold space counter
  # (Only handles 0-9 here; room for improvement)
  x; y/0123456789/1234567890/; h

  # If the block ends the file without blank line, then add the
  # new entry at end.
  $ { g; s/\(.*\)/whitelist.\1=ENTRY/p; b xx }

  # Label xx is here
  :xx
}
EOF
)"

이 흥미로운 도전에 정말 감사드립니다.

관련 정보