还包含 FS 字符的打印字段?

Printing field that also contains FS character?

要在 AWK 中处理的记录有这些可能的格式:

foobar为定长,serialno为变长,我要抓取的字段可能包含零个或多个下划线。

foobar_823932230_processname.txt
foobar_82393280_process_name.txt
foobar_8239330_foo_process_name.txt

期望输出

processname
process_name
foo_process_name

如果我使用 FS="[_.]" 那么我可以 print 这适用于第一条记录但不适用于第二条和第三条。

如何捕获序列号和 .txt 之间的所有内容?

我正在编辑需要更改的遗留 AWK 代码。一旦我正确捕获了这个字段,awk 进程就会继续生成额外的输出。

使用具有 -E 启用 ERE 的 sed(例如 GNU sed 和 BSD/OSX sed):

$ sed -E 's/([^_]+_){2}(.*)\.txt$//' file
processname
process_name
foo_process_name

使用任何 POSIX sed:

$ sed 's/\([^_]\{1,\}_\)\{2\}\(.*\)\.txt$//' file
processname
process_name
foo_process_name

使用 GNU awk:

$ awk '{[=12=]=gensub(/([^_]+_){2}(.*)\.txt$/,"\2",1)} 1' file
processname
process_name
foo_process_name

使用任何 awk:

$ awk '{sub(/([^_]+_){2}/,""); sub(/\.txt$/,"")} 1' file
processname
process_name
foo_process_name

这个cut + cut也应该有效:

cut -d_ -f3- file | cut -d. -f1
processname
process_name
foo_process_name

awk 解决方案将使用此正则表达式:

awk '{gsub(/^([^_]+_){2}|\..*$/, "")} 1' file

使用:

$ awk 'BEGIN{FS="[[:digit:]]+_"} {gsub(/\..+$/,"", ); print }' file
processname
process_name
foo_process_name

这通过将字段分隔符 FS 设置为数字后跟 _ 并通过剥离文件扩展名的结果变量 来实现gsub

您能否尝试仅使用显示的示例进行以下编写和测试。

awk 'match([=10=],/.*[0-9]+_/){print substr([=10=],RSTART+RLENGTH)}'  Input_file

您似乎需要调整现有的 awk 脚本来满足此要求。可惜 awk 没有 join 函数,但我们可以自己动手:

function join_fields(from, to, joiner,     result, i, sep) {
  for (i=from; i<=to; i++) {
    result = result sep $i
    sep = joiner
  }
  return result
}

演示:

awk -F '[_.]' '
  function join_fields(from, to, joiner,     result, i, sep) {
    for (i=from; i<=to; i++) {
      result = result sep $i
      sep = joiner
    }
    return result
  }

  {
      field = join_fields(3, NF-1, "_")
      print [=11=], "\t", field
  }
' <<END
foobar_823932230_processname.txt
foobar_82393280_process_name.txt
foobar_8239330_foo_process_name.txt
END
foobar_823932230_processname.txt     processname
foobar_82393280_process_name.txt     process_name
foobar_8239330_foo_process_name.txt      foo_process_name