Joel
Joel

Reputation: 11

How to delete a part of the text file if a pattern is found matching using tcl?

How can I remove a part of the text file if the pattern I am searching is matched?

eg:

  pg_pin (VSS) {
  direction : inout;
  pg_type : primary_ground;
  related_bias_pin : "VBN";
  voltage_name : "VSS";
}
leakage_power () {
  value : 0;
  when : "A1&A2&X";
  **related_pg_pin** : VBN;
}

My pattern is related_pg_pin. If this pattern is found i want to remove that particular section(starting from leakage power () { till the closing bracket}).

Upvotes: 1

Views: 664

Answers (2)

glenn jackman
glenn jackman

Reputation: 246744

Here's a "clever" way to do it:

proc unknown args {
    set body [lindex $args end]
    if {[string first "related_pg_pin" $body] == -1} {puts $args}
}
source file.txt

Your data file appears to be Tcl-syntax-compatible, so execute it like a Tcl file, and for unknown commands, check to see if the last argument of the "command" contains the string you want to avoid.

This is clearly insanely risky, but it's fun.

Upvotes: 0

Peter Lewerin
Peter Lewerin

Reputation: 13252

proc getSection f {
    set section ""
    set inSection false
    while {[gets $f line] >= 0} {
        if {$inSection} {
            append section $line\n
            # find the end of the section (a single right brace, #x7d)
            if {[string match \x7d [string trim $line]]} {
                return $section
            }
        } else {
            # find the beginning of the section, with a left brace (#x7b) at the end
            if {[string match *\x7b [string trim $line]]} {
                append section $line\n
                set inSection true
            }
        }
    }
    return
}

set f [open data.txt]
set g [open output.txt w]
set section [getSection $f]
while {$section ne {}} {
    if {![regexp related_pg_pin $section]} {
        puts $g $section
    }
    set section [getSection $f]
}
close $f
close $g

Starting with the last paragraph of the code, we open a file for reading (through the channel $f) and then get a section. (The procedure to get a section is a little bit convoluted, so it goes into a command procedure to be out of the way.) As long as non-empty sections keep coming, we check if the pattern occurs: if not, we print the section to the output file through the channel $g. Then we get the next section and go to the next iteration.

To get a section, first assume we haven't yet seen any part of a section. Then we keep reading lines until the end of the file is found. If a line ending with a left brace is found, we add it to the section and take a note that we are now in a section. From then on, we add every line to the section. If a line consisting of a single right brace is found, we quit the procedure and deliver the section to the caller.

Documentation: ! (operator), >= (operator), append, close, gets, if, ne (operator), open, proc, puts, regexp, return, set, string, while, Syntax of Tcl regular expressions

Syntax of Tcl string matching:

  • * matches a sequence of zero or more characters
  • ? matches a single character
  • [chars] matches a single character in the set given by chars (^ does not negate; a range can be given as a-z)
  • \x matches the character x, even if that character is special (one of *?[]\)

Upvotes: 3

Related Questions