在 Bash 中用字符串替换命令

时间:2021-02-26 16:46:52

标签: linux bash unix

我想检查文件 /etc/passwd 的哪些行以“/bin/bash”字符串(字段编号 7,“:”作为分隔符)结尾。 到目前为止,我已经编写了以下代码:

while read line
do
    if [ $("$line" | cut -d : -f 7)=="/bin/bash" ]
    then
        echo $line | cut -d : -f 1
        echo "\n"
    fi
done < /etc/passwd

目前,执行脚本会引发错误,显示错误解释(很可能是由于语法)。 如果您能帮助我,我将不胜感激。

4 个答案:

答案 0 :(得分:1)

您必须用空格将 == 运算符括起来。 [[[ 根据给定的参数数量做不同的事情:

if [ "$( echo "$line" | cut -d: -f7 )" == "/bin/bash" ]; ...

我实际上会这样做:在您阅读该行时将其解析为字段。

while IFS=: read -ra fields; do
    [[ ${fields[-1]} == "/bin/bash" ]] && printf "%s\n\n" "${fields[0]}"
done < /etc/passwd

答案 1 :(得分:0)

与其循环遍历行,然后检查 /bin/bash 部分,不如使用类似 之类的东西来获取所有所需的行,如下所示:

grep ':/bin/bash$' /etc/passwd

可选性,您可以使用 simple while 循环遍历行;

grep ':/bin/bash$' /etc/passwd | while read -r line ; do
    echo "Processing $line"
done

答案 2 :(得分:0)

不要做while read | cut。将 IFS 用作:

#!/bin/sh

while IFS=: read name passwd uid gid gecos home shell; do
        if test "$shell" = /bin/bash; then
                echo "$name"
        fi
done < /etc/passwd

但是对于这个特定的用例,最好这样做:

awk '$7 == "/bin/bash"{print $1}' FS=: /etc/passwd

您的代码存在的问题是一个常见错误。考虑这一行:

if [ $("$line" | cut -d : -f 7)=="/bin/bash" ]

假设您在 $line 中有一个值,其中最后一个字段是 /bin/dash。进程替换将插入字符串 /bin/dash,bash 将尝试执行:

if [ /bin/dash==/bin/bash ]

由于 /bin/bash==/bin/bash 是一个非空字符串,命令 [ /bin/bash==/bin/bash ] 成功返回。它执行任何类型的字符串比较。为了让 [ 进行字符串比较,您需要向它传递 4 个参数。例如,[ /bin/dash = /bin/bash ] 会失败。请注意,该调用的 4 个参数是 /bin/dash=/bin/bash][ 是一个非常奇怪的命令,需要它的最后一个参数是 ]。我强烈建议永远不要使用它,而是用它的表亲 test(非常密切相关,实际上 test[ 曾经链接到同一个可执行文件)替换它,它的行为与相同但不要求其最终参数为 ]

答案 3 :(得分:0)

这一行是错误的:

if [ $("$line" | cut -d : -f 7)=="/bin/bash" ]

另外,这不会做你想做的:

 echo "\n"

Bash echo 不理解反斜杠转义字符 -e.如果您想打印一个新行,只需使用 echo 但请注意 之前的回声:

echo $line | cut -d : -f 1

将添加一个换行符。

你应该经常检查你的脚本 shellcheck。正确的脚本是:

#!/usr/bin/env bash

while read -r line
do
    if [ "$(echo "$line" | cut -d : -f 7)" == "/bin/bash" ]
    then
        echo "$line" | cut -d : -f 1
    fi
done < /etc/passwd

但是请注意,您实际上并不需要一个非常缓慢且 可以使用以下 awk one-liner:

awk -v FS=: '$7 == "/bin/bash" {print $1}' /etc/passwd