다음과 같은 텍스트와 숫자가 포함된 파일이 있습니다.
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입니다( NR
awk로 표시됨) .질소수량오른쪽입력된 레코드 FNR
는 동일하지만 다음 입력 파일마다 재설정됩니다. 모든 행을 읽고 완료할 때까지 이 루프가 반복됩니다. 변수 twice=1
와 조건은 !twice
awk가 첫 번째 블록을 한 번만 실행하고 처음에는 입력 파일만 처리하도록 하는 데 사용됩니다.
이 줄은 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)]).