想要从模式开始获得第一个单词和单词' - '来自

时间:2016-07-21 22:59:35

标签: perl awk sed tcl

我的文件中有这些行:

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

如何借助模式搜索和替换来完成?

5 个答案:

答案 0 :(得分:2)

不确定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

答案 1 :(得分:1)

使用perl one liner with regex grouping

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

来自用户@mklement0的命令

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

答案 2 :(得分:0)

在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个......单词,这恰好是以“ - ”开头的单词。第二个解决方案查看每个参数并选择以“ - ”开头的参数。第三种解决方案是对第二种解决方案进行临时修改,拒绝作为负整数的参数。

使用fileutil中的Tcllib

可以略微简化相同的解决方案
package require fileutil

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

<强> ETA

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

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

文档: >= (operator)chancontinuefilefileutil (package)iflassignlistlmap (for Tcl 8.5)lmapopenpackageputsregexpsetstringwhile{*} (syntax)Syntax of Tcl regular expressions

Tcl字符串匹配的语法:

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

答案 3 :(得分:0)

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

  • 您没有名为getExtractRCMode等的实际程序
  • 您的选项全部采用-key value形式,您希望在其中找到密钥
  • 打印到stdout就是你想要的。
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 :(得分:0)

这可能适合你(GNU sed):

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

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