简体   繁体   中英

search a particular line and store it in another file using tcl

I have to look into a file log_file.txt which looks something like this:

*Jun 20 16:03:52.482 IST: DSL 0-FW: Data0:
*Jun 20 16:03:52.482 IST: DSL 0-FW: 0x20 0x7 
*Jun 20 16:03:52.482 IST: DSL 0-FW: Read from ID 0x369
*Jun 20 16:15:32.591 IST: DSL 0: IPC: Msg_type (4)
*Jun 20 16:15:33.591 IST: DSL 0: IPC: Msg_type (4)
*Jun 20 16:15:33.591 IST: DSL 0: IPC: Msg_type (4)
*Jun 20 16:15:33.839 IST: %LINK-3-UPDOWN: Interface changed state to down
*Jun 20 16:06:21.848 IST: DSL 0-FW: PHY: ack_control: id:0x1
*Jun 20 16:06:21.848 IST: DSL 0-FW: PHY: ackcontrol: 
*Jun 20 16:06:22.192 IST: DSL 0-FW: PHY: ack_control:

Here I have to search for lines containing DSL 0-FW: and store the line in another file. But I have to exclude the ones with DSL 0-FW: PHY . Is there a possible way to do this?

You could read the file line by line and use string first to filter on the lines you need in the other file. string first returns the position of a particular smaller string into a larger string. It returns -1 if the smaller string is not found.

# Assuming that the script is in the same directory as the file... otherwise 
# replace by the file path

# Read the log file
set fin [open "log_file.txt" r]
# Open a file for writing
set fout [open "output.txt" w]

# Read line by line
while {[gets $fin line] != -1} {
    # Check if "DSL 0-FW:" is in the line, if found, proceed
    if {[string first "DSL 0-FW:" $line] != -1} {

        # Check if "DSL 0-FW:" is in the line, if not found, proceed
        if {[string first "DSL 0-FW: PHY" $line] == -1} {
            puts $fout $line
        }
    }
}

close $fin
close $fout

Or you could perhaps use a regexp:

while {[gets $fin line] != -1} {
    # Check if "DSL 0-FW:" without " PHY" is in the line, if found, proceed
    if {[regexp -- {DSL 0-FW:(?! PHY)} $line]} {
        puts $fout $line
    }
}

Where DSL 0-FW:(?! PHY) will match if there is a DSL 0-FW: not followed by a PHY .


Actually, you could even use string match :

while {[gets $fin line] != -1} {
    # Check if "DSL 0-FW:" is in the line, if found, proceed
    if {[string match "DSL 0-FW:" $line]} {

        # Check if "DSL 0-FW:" is in the line, if not found, proceed
        if {![string match "DSL 0-FW: PHY" $line]} {
            puts $fout $line
        }
    }
}

Assuming it's not a problem to read the whole log file into memory:

set all [split [read -nonewline "log.file"] \n]
set wanted [lsearch -all -inline -regex {DSL 0-FW: (?!PHY:)} $lines]
set fh [open "partial.file" w]
puts $fh [join $wanted \n]
close $fh

This uses a negative lookahead to filter out the lines you don't want: http://tcl.tk/man/tcl8.5/TclCmd/re_syntax.htm#M25

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM