Tig*_*rex 4 grep bash shell-script quoting
我从标准输入读取字符串,我想显示匹配字符串的用户。问题是,如果用户输入字符 '[' 或包含它的字符串。
grep -F
不起作用,因为该行必须以字符串开头(^ - 这是一个带 -F 的简单字符)。此外,getent $user
不会很好,因为我只需要用户名而不是 id。
if [[ "$user" == *"["* ]]; then
echo -e "Invalid username.\n"
continue
fi
if ! getent passwd | grep "^$user:"; then
echo -e "Invalid username.\n"
continue
fi
Run Code Online (Sandbox Code Playgroud)
这是'['的解决方法,还有其他方法吗?
awk
最有可能完成这项工作,但我对此一无所知,我对 grep 感兴趣。
小智 10
要么将其转义,要么将其放入字符类中,大致如下:
grep '\['
grep '[[]'
grep -e "${user//\[/\\\[}"
Run Code Online (Sandbox Code Playgroud)
${var//c/d}
shell 变量中的语法=>$var
我们将所有字符替换c
为d
. 现在,在您的情况下,c
is[
但碰巧[
在此语法中很特殊(它进行 globbing),因此我们需要通过在它前面加上反斜杠来转义它,即\[
.
现在来到更换部件,我们需要的是一个\[
在那里。但同样,在这种参数替换的语法中,\
和[
都是特殊的,${var//...}
因此两者都需要,是的,你猜对了,反斜杠导致表达式\\\[
:: "${var//\[/\\\[}"
HTH
[
不是为正则表达式转义的唯一字符。所有的 RE 运算符都包括.
在用户名中常见的(r.ot
例如作为正则表达式匹配root
)。
此外,您的方法 ( getent passwd | grep "^$user:"
) 也是无效的,例如它不会标记root:0
为无效。
在这里,最好使用awk
:
user_valid() {
getent passwd |
U="$1" awk -F: '$1 == ENVIRON["U"] {found = 1; exit}
END {exit(1 - found)}'
}
Run Code Online (Sandbox Code Playgroud)
现在,并非所有用户数据库都允许这样的枚举。
$ getent passwd | grep stephane
$ id -u stephane
10631
$ getent passwd stephane
stephane:*:10631:10631:Stephane Chazelas:/export/./home/stephane:/bin/zsh
Run Code Online (Sandbox Code Playgroud)
就我而言,该用户位于 LDAP 数据库中。枚举被禁用(可能有数千个用户),但我仍然可以单独查询/解析用户。
所以在这里,为了验证用户,最好直接为该用户查询用户数据库。例如,使用id
命令(与 相反的标准命令getent
):
user_valid() {
case $1 in
(*[!0-9]*) id -u -- "$1" > /dev/null 2>&1;;
(*) false;;
esac
}
Run Code Online (Sandbox Code Playgroud)
(我们单独处理全数字用户,因为id
在这种情况下,某些实现会为您提供用户 ID 的信息。在大多数系统中,用户名不能是数字(这会破坏大多数需要用户名或用户名的命令) ids 作为参数(如id
上面的那些ps
,find
...)))。