패턴 모양을 기준으로 파일 편집

패턴 모양을 기준으로 파일 편집

다음과 같은 텍스트와 숫자가 포함된 파일이 있습니다.

state(1, s(1,a), [s(1,b)]).
state(1, s(1,b), [s(1,a)]).
state(1, s(2,a), [s(2,b)]).
state(1, s(2,b), [s(2,a)]).
state(1, s(3,a), [s(3,b)]).
state(1, s(3,b), [s(3,a)]).
state(1, s(4,a), [t(1), t(2)]).
state(1, s(5,a), [t(1), t(3)]).
state(1, s(6,a), [s(6,b)]).
state(1, s(6,b), [s(6,a)]).
...so on

s(x,y)의 숫자를 다음과 같이 변경하고 싶습니다.

state(1, p(1), 0, [p(2)]).
state(1, p(2), 0, [p(1)]).
state(1, p(3), 0, [p(4)]).
state(1, p(4), 0, [p(3)]).
state(1, p(5), 0, [p(6)]).
state(1, p(6), 0, [p(5)]).
state(1, p(7), -1, [t(1), t(2)]).
state(1, p(8), -1, [t(1), t(3)]).
state(1, p(9), 0, [p(10)]).
state(1, p(10), 0, [p(9)]).
...so on

상태의 세 번째 매개변수에 있는 0과 -1은 단순히 ss(또는 pp) 연결의 존재/존재(0으로 표시) 또는 연결의 부재(-1로 표시)를 나타냅니다.

나는 "sed"를 시도했지만 전혀 성공하지 못했습니다.

몇 가지 팁이나 해결 방법을 얻을 수 있나요?

답변1

쉘 루프 대신 적절한 텍스트 처리 도구를 사용하십시오.:

gawk -F'(,[[:blank:]]+\\[?|\\]\\)\\.)' '!twice{ seen[$2]=NR; next } {
    print $1, "p(" FNR ")", (($3 in seen)?"0, [p("seen[$3]")":"-1, ["$3", "$4)"]).";
}' OFS=', ' infile twice=1 infile

필드 구분 기호를 ,<one-or-more-whitespaces><with-optional-]>또는 집합 으로 정의합니다.]).

입력 파일을 infile두 번 처리하므로 먼저 위에 설정된 FS를 기반으로 두 번째 필드를 읽고 이를 연관된 seen명명된 배열에 추가합니다. 이 배열의 키는 두 번째 필드 내용이고 각 값은 NR입니다( NRawk로 표시됨) .질소수량오른쪽입력된 레코드 FNR는 동일하지만 다음 입력 파일마다 재설정됩니다. 모든 행을 읽고 완료할 때까지 이 루프가 반복됩니다. 변수 twice=1와 조건은 !twiceawk가 첫 번째 블록을 한 번만 실행하고 처음에는 입력 파일만 처리하도록 하는 데 사용됩니다.

이 줄은 print두 번째 실행을 위한 것이며 첫 번째 필드를 인쇄한 다음 p(#)(여기서 #s는 FNR로 재생산됨) seen배열에서 일치하는 항목이 발견되면 배열의 모든 키에 대해 세 번째 필드를 확인합니다. , 그런 다음 인쇄합니다 0, [p(#)]).( #배열에서 일치하는 키 값이 표시되는 위치 번호는 어디에 있습니까?). 그렇지 않으면 인쇄합니다.-1, [...]).

답변2

입력 파일을 "sample.txt"라고 부르자

먼저 파일에 0과 -1 비트를 넣어야 합니다.

cat sample.txt | sed 's/, \[s/, 0, \[s/g' | sed 's/, \[t/, -1, \[t/g' > sample1.txt

새로운 "sample1.txt" 파일이 있으면 다음 bash 스크립트(convert.bash)를 실행할 수 있습니다.

#!/bin/bash

k=0
maxstates=$(wc -l "$1" | gawk '{print $1}')

for i in $(seq 1 "$maxstates")
do
    count=$(grep -c "s($i,a)" "$1")
    if [ "$count" -ne 0 ]
    then
        k=$((k + 1))
        sed -i "s/s($i,a)/p($k)/g" "$1"
    fi
    count=$(grep -c "s($i,b)" "$1")
    if [ "$count" -ne 0 ]
    then
        k=$((k + 1))
        sed -i "s/s($i,b)/p($k)/g" "$1"
    fi
done

이제 파일을 실행하십시오.

bash convert.bash sample1.txt

샘플1.txt를 로컬로 편집하며 새 콘텐츠는 다음과 같습니다.

state(1, p(1), 0, [p(2)]).
state(1, p(2), 0, [p(1)]).
state(1, p(3), 0, [p(4)]).
state(1, p(4), 0, [p(3)]).
state(1, p(5), 0, [p(6)]).
state(1, p(6), 0, [p(5)]).
state(1, p(7), -1, [t(1), t(2)]).
state(1, p(8), -1, [t(1), t(3)]).
state(1, p(9), 0, [p(10)]).
state(1, p(10), 0, [p(9)]).

관련 정보