使用 AWK 在某个字段中搜索相等性

Search equality in a certain field with AWK

我试图从 /etc/passwd 中获取名称,使用 awk 仅在每行的第 5 个字段中搜索,然后剪切该行的某些部分并将其打印出来。

这是我写的,但似乎不起作用:

for iter in "$@";
do cat /etc/passwd | awk -F ":" '==$iter' | cut -d":" -f6;
done;

关于定界符语法,我想一切都应该没问题吧? 所以我想我的问题出在 $5==$iter 上。 如何将 $5==$iter 更改为 - 如果该行的第 5 个字段包含我的 $iter var,则剪切等等..

抱歉我的无知,我是初学者:) 提前致谢。

How do I use shell variables in an awk script?

-v 应该用于将 shell 变量传递给 awk。此外,没有理由在此处使用 catcut

for iter in "$@"; do
  awk -F: -v iter="$iter" '==iter { print  }' </etc/passwd
done

您也可以在 bash 中执行所有操作,例如:

#!/bin/bash

declare -A passwd               # declare a associative array

# build the associative array "passwd" with the
# 5th field as a "key" and 6th field as "value"
while IFS=$':\n' read -a line; do      # emulate awk to extract fields
    [[ -n "${line[4]}" ]]  || continue # avoid blank "keys"
    passwd["${line[4]}"]=${line[5]}    # in bash, arrays starting in "0"
done < /etc/passwd

for iter in "$@"; do
    if [ ${passwd[$iter] + 'x'} ]; then
        echo ${passwd[$iter]}
    fi
done

(此版本未进入第 5 个字段的帐户倍数值)

这里有一个更好的版本,也可以处理空白值,ike./script.sh '':

while IFS=$':\n' read -a line; do
    for iter in "$@"; do
        if [ "$iter" == "${line[4]}" ]; then
            echo ${line[5]}
            continue
        fi
    done
done < /etc/passwd

纯 awk 解决方案可以是:

#!/usr/bin/awk -f

BEGIN {
    FS = ":"
    for ( i = 1; i < ARGC; i++ ) {
        args[ARGV[i]] = 1
        delete ARGV[i]
    }
    ARGV[1] = "/etc/passwd"
}
( in args) { print  }

你可以调用 ./script.awk -f 'param1' 'param2'.

正如 Charles Duffy 评论的那样,如果代码不需要每次都读取 /etc/passwd,您的代码会更有效率。虽然这个特定的循环可能不需要优化(毕竟,/etc/passwd 通常不会那么长,而且大多数 OS 会在第一次读取后缓存文件),但它会是有趣的是看到一个 awk 脚本只读取文件一次。

也就是说,这是另一个只调用一次 awk 的实现:

printf "%s\n" "$@" | awk -F: '
  NR == FNR { etc_passwd[  ] = ;  next } 
            { print [=10=] , etc_passwd[ [=10=] ]   }
' /etc/passwd  /dev/stdin 

NR == FNR 条件是一个惯用语,它导致它的关联命令只对 awk 脚本后面的文件列表中的第一个文件执行(即读取 /etc/passwd).