2016-09-16 2 views
0

파일의 날짜를 업데이트해야합니다. 그러므로 나는 오늘 (#define __VERSION_DAY 23)의 행을 찾고 필사적으로 그것을 업데이트하려고 노력하고있다.tcl을 사용하여 파일에서 값 찾기 및 바꾸기

while {([gets $fp_Vers line] >= 0)} { 

    if { [string match -nocase "#define*__VERSION_DAY*" $line] } { 
     # Get the current day 
     set day [clock format $systemTime -format {%d}] 
     set line [split $line] 
     # Replace the old value 
     set line [lreplace $line 2 $day] 
     puts $fp_Vers $line 
    } 
} 

{#define} __VERSION_DAY 파일의 끝에 다음을 넣습니다. 이해할 수 없습니다 ...
1) 주위에 대괄호가있는 이유는 무엇입니까?
2) 현재 날짜 (예 : 16)의 값이 누락 된 이유 2)

귀하의 기여에 감사드립니다!

답변

0

tkcon과 같은 Tcl 쉘에서 명령을 실행하면 쉽게 어떤 문제가 있는지 알 수 있습니다. 도망 치지 말고 일리있는 일을 피하는 것이 좋습니다. 이하, (%로 시작하는 라인이 결과 혼합한다. 명령

% set line {#define __VERSION_DAY 23} 
#define __VERSION_DAY 23 
set day 16 
16 
% set line [split $line] 
{#define} __VERSION_DAY 23 

리스트로 문자열을 분할 할 때, 캐릭터의 표현의 변화는 (가능 뒷부분 주위 따라서 괄호 #define을리스트를 재생성 할 수 있도록 이는 기타) 잘못된 목록 항목이 될 것

set line [lreplace $line 2 $day] 
{#define} __VERSION_DAY 

lreplace 명령은 다음 인수를 취합니다. listfirst (인덱스) last?element ...? (0 개 이상의 요소 (인덱스)가 R 교체 와 함께). day (16)의 내용은 아무 것도 대체하지 않을 범위의 마지막 색인으로 해석됩니다.

대신을 시도해보십시오

% set line [join [lreplace [split $line] 2 2 $day]] 
#define __VERSION_DAY 16 

파일에 날짜 필드를 업데이트 관련하여, 가장 좋은 건 아마 이런 식으로 어느 정도 그것을 할 :

set day 16 
set f [open $filename] 
set lines [split [string trim [read $f]] \n] 
close $f 

set result {} 
set tag {#define __VERSION_DAY } 
set pattern [string map {{ } *} $tag] 
foreach line $lines { 
    if {[string match -nocase $pattern $line]} { 
     lappend result $tag$day 
    } else { 
     lappend result $line 
    } 
} 

set f [open $filename2 w] 
puts -nonewline $f [join $result \n] 
close $f 

참고 : 그렇지 출력을 $result은 변수의 내용이 목록 추가 행으로 작성된 목록 구조를 유지하기 위해 인용되기 때문에 직접 입력해야합니다. 개행 문자를 사용하여 행을 결합하면 구조가 출력에서 ​​작동하는 평면 텍스트로 변경됩니다. Tcllib에서 fileutil를 사용

또는, 전략은 기본적으로 동일하다는 것을

package require fileutil 

set day 16 
set tag {#define __VERSION_DAY } 
set pattern [string map {{ } *} $tag] 
set f [open $filename2 w] 
::fileutil::foreachLine line $filename { 
    if {[string match -nocase $pattern $line]} { 
     puts $f $tag$day 
    } else { 
     puts $f $line 
    } 
} 
close $f 

참고. 첫 번째 솔루션은 변수에 목록 추가 행을 사용하고 나중에 결합 된 텍스트를 인쇄합니다. 두 번째 솔루션 대신 각 줄을 직접 인쇄합니다. 하위 레벨 open - read - close 직접 인쇄를 사용하는 솔루션이나 fileutil 라인이있는 솔루션을 변수에 추가하는 것을 막을 수있는 방법은 없습니다.

문서 : close, fileutil (package), foreach, if, join, lappend, lreplace, open, package, puts, read, set, split, string

+1

Tcl의 목록에 따르면 _also_는 결과가 유효한 단어가 아닌 첫 번째 단어에서 지정된 단일 명령을 _no_ 예기치 않은 대체와 함께 인수로 전달하는 유효한 스크립트임을 보증합니다 (백 슬래시와 중괄호의 최소 개수는 직렬화). 따옴표로 묶지 않으면 처음에 '#'이 해당 제약을 위반하게됩니다. –

+0

Peter와 Donal의 상세한 답변을 보내 주셔서 감사합니다. – Stingray

+0

피터 (Peter)의 첫 번째 제안을 시도했습니다. ... foreach line $ lines { if {[string string -nocase $ pattern $ line]} {...'날짜가 업데이트되고 정확한 위치에 ... 각 줄은 대괄호'{...} '안에 넣어집니다. 그리고 10 개의 라인은 하나의 긴 라인으로 끝납니다. – Stingray

0

다른 상황에서 의미가있는 Tcl 목록 serialization에 대한 다른 규칙을 만족시키기 때문에 split은 예상치 못한 인용문을 추가하는 것이 문제입니다. 이 경우 가장 쉬운 해결 방법은 regsub을 사용하여 교체를 수행하는 것입니다. 정규 표현식은 분명히 날카로운 도구이지만 어쨌든 때로는 올바른 접근 방식이기도합니다.

# Factor a few bits out for convenience 

# The RE pattern we're looking for. 
set VERSION_RE {(#define\s+_VERSION_DAY\s*).+} 

# Get the current day as a replacement pattern 
set dayReplacement [clock format $systemTime -format {\1%d}] 

while {[gets $fp_Vers line] >= 0} { 
    if {[regsub $VERSION_RE $line $dayReplacement line]} { 
     # If we did the replacement, write the new value out 
     puts $fp_Vers $line 
    } 
} 

나는 당신이 당신이 작성하는 경우 재설정 seek 또는 chan truncate을 할 필요가 의심되는,하지만 그건 당신의 문제입니다.


regsub이 함께 사용될 때 변수 간 기록을 인수 티클 그 결과가 대체 실시 수가 있기 때문에이 작동한다. -all 스위치가 없다면 그것은 사실 부울입니다. 발견 된 패턴이 대체 되었습니까?

+0

아마도 tcl에 사용하는 Quartus 14.0 쉘은 일부 명령이나 다른 동작을 지원하지 않을 수 있습니다.나는 그것을위한 버전을 찾지 못했지만, Quartus 11.1은 이미 8.5 (Tcl DeveloperXchange에서 제공되는 Tcl/Tk 버전 8.5)를 지원합니다. 다음 출력을 얻었습니다 : '% # 우리가 찾고있는 RE 패턴. VERSION_RE 설정 %는 {. (#DEFINE의 \ S + _VERSION_DAY \들 *) +} %는두고 $ VERSION_RE ** (#DEFINE의 \ S + _VERSION_DAY \ S *) + **' – Stingray

+0

@Stingray :. 당신 ' 거기에 있어서는 안되는 괄호 안에 공백을 추가했습니다. –

+0

@Peter : 힌트를 주셔서 감사합니다. tcl 스크립트에는 내가 가지고 있지 않습니다. 'set VERSION_RE {(#define \ s + _VERSION_DAY \ s *). +}'여기에 메시지를 편집하는 동안 나타난 것 같습니다. – Stingray

관련 문제