使用 awk 命令打印每个单词的最后一个字母以生成字符串

print the last letter of each word to make a string using `awk` command

我有这条线

UDACBG UYAZAM DJSUBU WJKMBC NTCGCH DIDEVO RHWDAS

我正在尝试使用 awk 命令打印每个单词的最后一个字母以创建一个字符串

awk '{ print substr(,6) substr(,6) substr(,6) substr(,6) substr(,6) substr(,6) }'

如果我不知道一个单词包含多少个字符,打印 $column 的最后一个字符的正确命令是什么,而不是重复 substr 命令,我该如何使用它仅一次打印不同列中的特定字符

如果您只有这一行要处理,您可以使用

awk '{for (i=1;i<=NF;i++) r = r "" substr($i,length($i))} END{print r}' file

如果输入多行:

awk '{r=""; for (i=1;i<=NF;i++) r = r "" substr($i,length($i)); print r}' file

详情:

  • {for (i=1;i<=NF;i++) r = r "" substr($i,length($i)) - 遍历当前记录中的所有字段,i 是字段 ID,$i 是字段值,每个字段的所有最后一个字符(检索substr($i,length($i))) 附加到 r 变量
  • END{print r}awk 脚本完成处理后打印 r 变量。
  • 在第二种解决方案中,r值在每行处理开始时被清除,并在处理完当前记录中的所有字段后打印其值。

参见 online demo:

#!/bin/bash
s='UDACBG UYAZAM DJSUBU WJKMBC NTCGCH DIDEVO RHWDAS'
awk '{for (i=1;i<=NF;i++) r = r "" substr($i,length())} END{print r}' <<< "$s"

输出:

GMUCHOS

使用 GNU awk 和 gensub:

$ gawk '{print gensub(/([^ ]+)([^ ])( |$)/,"\2","g")}' file

输出:

GMUCHOS

第一个解决方案: 使用 GNU awk 你可以尝试遵循 awk 程序,编写并测试显示示例。

awk -v RS='.([[:space:]]+|$)' 'RT{gsub(/[[:space:]]+/,"",RT);val=val RT} END{print val}' Input_file

说明: 将记录分隔符设置为任何字符后跟 space 或 value/line 的结尾。然后根据 OP 的要求从获取的值中删除不必要的 newline/spaces ;继续创建具有 RS 匹配值的 val,最后当 awk 程序完成读取整个 Input_file 然后打印变量的值。



第二个解决方案: 使用记录分隔符作为 null 并在值上使用 match 函数以匹配正则表达式 (.[[:space:]]+)|(.$) 要仅在找到每个匹配项时获取最后一个字母值,请继续将匹配值添加到变量中,最后在 awk 程序打印变量值的 END 块中。

awk -v RS= '
{
  while(match([=11=],/(.[[:space:]]+)|(.$)/)){
    val=val substr([=11=],RSTART,RLENGTH)
    [=11=]=substr([=11=],RSTART+RLENGTH)
  }
}
END{
  gsub(/[[:space:]]+/,"",val)
  print val
}
'  Input_file

sed 的任务是在单行上进行简单替换:

$ sed 's/[^ ]*\([^ ]\) *//g' file
GMUCHOS

GNU awk 的另一种方法是使用 FPATsplit by and keep the content:

gawk 'BEGIN{FPAT="\S\>"}
{   s=""
    for (i=1; i<=NF; i++) s=s $i
    print s
}' file
GMUCHOS

或者更简洁和地道的:

gawk 'BEGIN{FPAT="\S\>";OFS=""}{=}1' file
GMUCHOS

(感谢大维

您还可以将 gensub 用于:

gawk '{print gensub(/\S*(\S\>)\s*/,"\1","g")}' file
GMUCHOS

两者的优点是单个字母“单词”处理得当:

s2='SINGLE X LETTER Z'

gawk 'BEGIN{FPAT="\S\>";OFS=""}{=}1' <<< "$s2"
EXRZ

gawk '{print gensub(/\S*(\S\>)\s*/,"\1","g")}' <<< "$s2"
EXRZ

哪里接受的答案和大多数在这里:

awk '{for (i=1;i<=NF;i++) r = r "" substr($i,length())} END{print r}' <<< "$s2"
ER       # WRONG

gawk '{print gensub(/([^ ]+)([^ ])( |$)/,"\2","g")}' <<< "$s2"
EX RZ    # WRONG

使用很多工具

$ tr -s ' ' '\n' <file | rev | cut -c1 | paste -sd'[=10=]'

GMUCHOS

将单词分隔成行,反转以便我们可以轻松选择第一个字符,最后将它们重新粘贴在一起而不使用分隔符。不是最短的解决方案,但我认为是最简单的解决方案...

我将如下利用 GNU AWK,令 file.txt 内容为

UDACBG UYAZAM DJSUBU WJKMBC NTCGCH DIDEVO RHWDAS

然后

awk 'BEGIN{FPAT="[[:alpha:]]\>";OFS=""}{=;print}' file.txt

输出

GMUCHOS

解释:通知AWK 处理单词末尾的任何字母字符,并使用空字符串作为输出字段分隔符。 = 用于通过使用指定的 OFS 来触发线路重建。如果您想了解更多关于 start/end 的信息,请阅读 GNU Regexp Operators.

(在 gawk 4.2.1 中测试)

另一个 GNU 解决方案 awk:

awk '{[=10=]=gensub(/[^[:space:]]*([[:alpha:]])/, "\1","g"); gsub(/\s/,"")} 1' file
GMUCHOS
  • gensub() 获取字符,gsub() 删除它们之间的空格。

或使用patsplit():

awk 'n=patsplit([=11=], a, /[[:alpha:]]\>/) { for (i in a) printf "%s", a[i]} i==n {print ""}' file
GMUCHOS