【问题标题】:want to get first word and word starting from pattern '-' from the line想要从该行中获取从模式“-”开始的第一个单词和单词
【发布时间】:2016-11-25 17:19:46
【问题描述】:

我的文件中有这些行:

getExtractRCMode -engine postRoute -coupled true -effortLevel signoff -qrcCmdType partial
getNanoRouteMode -drouteMinimizeLithoEffectOnLayer {t t t t t t t t t t t}

我无条件想要第一个单词,并且只想要那些以-开头的后续单词

预期输出:

getExtractRCMode -engine -coupled -effortLevel -qrcCmdType 
getNanoRouteMode -drouteMinimizeLithoEffectOnLayer

我将如何借助模式搜索和替换来做到这一点?

【问题讨论】:

  • 不拘一格的标签集。

标签: perl awk sed tcl


【解决方案1】:

这可能对你有用(GNU sed):

sed -r 's/(\s-\S+)|\s\S+/\1/g' file

使用模式匹配、交替和反向引用来实现所需的结果,即自行替换所需的字符串,否则将其删除。

【讨论】:

    【解决方案2】:

    在 Tcl 中(具有基本 I/O 的三种解决方案):

    set f [open file]
    # 1:
    while {[chan gets $f line] >= 0} {
        set args [lassign $line word]
        puts [list $word {*}[lmap {a b} $args {
            set a
        }]]
    }
    chan seek $f 0
    # 2:
    while {[chan gets $f line] >= 0} {
        set args [lassign $line word]
        puts [list $word {*}[lmap arg $args {
            if {[string match -* $arg]} {
                set arg
            } else {
                continue
            }
        }]]
    }
    chan seek $f 0
    # 3:
    while {[chan gets $f line] >= 0} {
        set args [lassign $line word]
        puts [list $word {*}[lmap arg $args {
            if {[string match -* $arg] && ![string is integer $arg]} {
                set arg
            } else {
                continue
            }
        }]]
    }
    chan close $f
    

    第一个解决方案只是选择参数列表中的第 0 个、第 2 个、... 单词,恰好是那些以“-”开头的单词。第二种解决方案查看每个参数并选择以“-”开头的参数。第三种解决方案是对第二种解决方案的临时修改,它拒绝负整数参数。

    使用来自Tcllibfileutil 可以稍微简化相同的解决方案:

    package require fileutil
    
    ::fileutil::foreachLine line file {
        set args [lassign $line word]
        puts [list $word {*}[lmap {a b} $args {
            set a
        }]]
    }
    

    等等

    预计到达时间

    不用说,其他答案中的解决方案也可以在 Tcl 中使用,例如:

    ::fileutil::foreachLine line file {
        puts [regexp -inline -all {(?:^|-)\w+} $line]
    }
    

    文档: >= (operator), chan, continue, file, fileutil (package), if, lassign, list, lmap (for Tcl 8.5), lmap, open, package, puts, regexp, set, string, while, {*} (syntax), Syntax of Tcl regular expressions

    Tcl 字符串匹配的语法:

    • * 匹配零个或多个字符的序列
    • ? 匹配单个字符
    • [chars] 匹配由 chars 给出的集合中的单个字符(^ 是否 not 否定;范围可以作为 az 给出)李>
    • \x 匹配字符 x,即使该字符是特殊字符(*?[]\ 之一)

    【讨论】:

    • 感谢您的帮助。 #2 解决方案非常有用,因为它选择以“-”开头的那个。
    • getViaGenMode -partial_overlap_threshold -1 -holdFixingCells ClkBuf1 ClkBuf2
    • 还有这样的输出吗?
    • getViaGenMode -partial_overlap_threshold -holdFixingCells
    • 这里-1是用户设置的值。所以我也想忽略它。如果我使用选项 #1 ,那么我将获得 clkbuf2 。
    【解决方案3】:

    另一个 Tcl 角度是将您的数据视为代码,并利用 unknown 机制。假设:

    • 您没有名为 getExtractRCMode 等的实际过程。
    • 您的选项都采用-key value 的形式,您希望在其中查看密钥
    • 打印到标准输出是您想要的。
    rename unknown _original_unknown
    proc unknown args {
        set cmdname [lindex $args 0]
        array set options [lrange $args 1 end]
        puts [concat $cmdname [array names options]]
    }
    
    set data {getExtractRCMode -engine postRoute -coupled true -effortLevel signoff -qrcCmdType partial
    getNanoRouteMode -drouteMinimizeLithoEffectOnLayer {t t t t t t t t t t t}}
    
    eval $data
    

    打印所需的输出。

    【讨论】:

      【解决方案4】:

      使用带正则表达式分组的 perl one liner

      perl -e 'while (<>){ @ar = m/(^\w+|-\w+)/g; print"@ar\n"; }' file.txt
      

      来自用户@mklement0的命令

      perl -lne 'print join " ", m/^\w+|-\w+/g;' file.txt
      

      【讨论】:

      • @mklement0 Yaaa.. 你真的很棒。 :)
      • 改进您的正则表达式:m/^\w+|(?&lt;=\s)-\w+/g -- 使用积极的后向查找来查找连字符前的空格。否则你会匹配“foo -bar baz-qux”中的“-qux”
      【解决方案5】:

      不太清楚with the help of pattern search and replace 是什么意思,但这里有几种方法可以从您发布的输入中获得所需的输出:

      $ sed 's/ [^-][^ ]*//g' file
      getExtractRCMode -engine -coupled -effortLevel -qrcCmdType
      getNanoRouteMode -drouteMinimizeLithoEffectOnLayer
      
      $ awk '{printf "%s", $1; for (i=2;i<=NF;i++) if ($i ~ /^-/) printf "%s%s", OFS, $i; print ""}' file
      getExtractRCMode -engine -coupled -effortLevel -qrcCmdType
      getNanoRouteMode -drouteMinimizeLithoEffectOnLayer
      
      $ awk -F ' [^-][^ ]*' '{$1=$1; gsub(/ +/," ")}1' file
      getExtractRCMode -engine -coupled -effortLevel -qrcCmdType
      getNanoRouteMode -drouteMinimizeLithoEffectOnLayer
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多