使用 awk 或 sed 进行列编辑。如何打印下面的图案?

使用 awk 或 sed 进行列编辑。如何打印下面的图案?

Sample Input:

title          role        subject
name-JOHN      student      math
school         state        NY
county         street       Phone
name-TOM       student      math
school         state        TX
county         street       Phone
name-LILLY     student      math
school         state        LA
county         street       Phone
name-ROSY      student      math
school         state        WA
county         street       Phone
garbage line 1
garbage line 2

Desired Output

JOHN     NY
TOM      TX
LILLY    LA
ROSY     WA

底部 2 条垃圾线必须消失。我想使用 AWk 还是 SED?

我正在运行 Sun 操作系统。

答案1

由 GNU 提供sed

sed -n '/^name-/{s///;N;s/[a-z].*\s//p}' file
JOHN      NY
TOM       TX
LILLY     LA
ROSY      WA

由 GNU 提供awk

awk -F'[ -]+' '/name/{a=$2}/state/{print a,$3}' OFS='\t' file
JOHN    NY
TOM     TX
LILLY   LA
ROSY    WA

经过grep

grep -o '[[:upper:]]\{2,\}' file | paste - -
JOHN    NY
TOM     TX
LILLY   LA
ROSY    WA

答案2

这是另一种 awk 方式(我现在看到,这只是 @Costas 的一个丑陋版本):

$ awk -F'[- ]' '($1~/name/){k=$2}($1~/school/){print k,$NF}' file
JOHN NY
TOM TX
LILLY LA
ROSY WA

您还可以使用grep

$ grep -oP '^(name-\K\S+|school.*\s+\K.*)' file | paste - -
JOHN    NY
TOM TX
LILLY   LA
ROSY    WA

当然,在您的特定示例中,您可以只查找大写字母:

$ grep -Eo '[A-Z]{2,}' file | paste - -

或者perl:

$ perl -lne '$n=$1 if /^name-(\S+)/; /^school.*\s+(.+)/ && print "$n\t$1"' file

或者另一个 perl:

$ perl -007ne 'print join "\n", (/name-(\S+?)\s.*?state\s+(..)\n/gsm)' file | paste - -

答案3

awk '/name/ {gsub(/name-/,""); printf "%s\t",$1} /school/ {print $3}' file
JOHN    NY
TOM     TX
LILLY   LA
ROSY    WA

答案4

需要明确的是,您使用的是“旧awk”( /usr/bin/awk/) 还是“新awk”( /usr/xpg6/bin/awk)?一个在线的手册页参考GNU Awk 的帮助页面非常清楚地指出了区别。

假设如果您指的是“new awk”,您可以通过使用变量赋值-v,您也可以考虑这一点:

$ awk -v RS='name-' -v OFS='\t' 'NR>1{print $1,$6}' sample.txt
JOHN    NY
TOM     TX
LILLY   LA
ROSY    WA

我们设置记录分隔符 ( -v RS='name-'),以便awk将名称和状态分别解释为第一个 ( $1) 和第六个 ( $6) 字段。然后我们还设置输出字段分隔符 ( -v OFS='\t') 以执行所需的格式设置。条件NR>1只是跳过第一行。

编辑

awk 'BEGIN{RS="name-";OFS="\t"}NR>1{print $1,$6}' sample.txt

即使对于“老”来说这也应该是可行的awk,请测试一下。保持“新awk”的最初建议不变。

相关内容