还包含 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:
$ 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
要在 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:
$ 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