在一个bash脚本中,我如何对用户输入进行净化处理?

54

我正在寻找最佳的方法来获取一个简单的输入:

echo -n "Enter a string here: "
read -e STRING

通过删除非字母数字字符,转换为小写,并用下划线替换空格来清理它。

顺序是否重要?tr是处理此操作的最佳/唯一方法吗?

5个回答

56

正如 dj_segfault 指出的那样,shell 可以为您完成大部分工作。不过,看起来你需要借助一些外部工具来将字符串转换为小写。对于这个问题,您有许多选择,例如上面提到的 perl 一行命令等等,但我认为 tr 可能是最简单的。

# first, strip underscores
CLEAN=${STRING//_/}
# next, replace spaces with underscores
CLEAN=${CLEAN// /_}
# now, clean out anything that's not alphanumeric or an underscore
CLEAN=${CLEAN//[^a-zA-Z0-9_]/}
# finally, lowercase with TR
CLEAN=`echo -n $CLEAN | tr A-Z a-z`

这里的顺序有些重要。我们希望去掉下划线,并将空格替换为下划线,所以必须首先去除下划线。等到最后再传递参数到tr命令,我们就知道只有字母数字和下划线,而且可以确定没有空格,因此无需担心shell解释特殊字符。


2
读者注意:如果您无法让此程序正常工作,请检查您的shebang,看看您是否调用了bash或sh,并查看您的系统如何解释“sh”。 - JD.
2
从Bash 4开始,它也可以进行大小写修改。 lowercase = $ {CLEAN,,} [Bash Hackers Wiki](http://wiki.bash-hackers.org/syntax/pe)以比man页面更易读的方式解释了参数扩展。 - toxalot
干得好。我之前不知道这些shell功能。谢谢!我刚刚发现zsh允许您实际上嵌套所有这些,因此您可以在一行中完成:echo -n ${${${str//_/}// /_}//[^a-zA-Z0-9_]/} | tr A-Z a-z..虽然我不建议将如此难以理解的内容放入脚本中。 :) (编辑:格式) - Jon Carter
非常好。在所有a-z A-Z调用之前,可能还需要一个: LC_ALL=C,以确保它不会留下任何奇怪的东西(取决于您的语言环境或其他人的语言环境,a-z、A-Z甚至0-9都可能意味着很多不同的东西...) - Olivier Dulac

45

Bash可以自己完成所有操作,非常感谢。如果您查看参数展开部分的手册页面,您会发现bash具有内置的替换、子字符串、修剪、右修剪等功能。

要消除所有非字母数字字符,请执行

CLEANSTRING=${STRING//[^a-zA-Z0-9]/}

这就是奥卡姆剃刀原理。不需要启动另一个进程。


说得好,回答很棒。我甚至没有意识到自己正在使用参数扩展。 - Devin Reams
3
这是一个针对某些规格的好答案,但它没有将空格改为下划线。 - Axeman

4

对于Bash >= 4.0

CLEAN="${STRING//_/}" && \
CLEAN="${CLEAN// /_}" && \
CLEAN="${CLEAN//[^a-zA-Z0-9]/}" && \
CLEAN="${CLEAN,,}"

这对于使用docker/podman编程创建容器名称尤其有用。然而,在这种情况下,您还需要删除下划线:
# Sanitize $STRING for a container name
CLEAN="${STRING//[^a-zA-Z0-9]/}" && \
CLEAN="${CLEAN,,}"

0

经过一番搜索,似乎tr确实是最简单的方法:

export CLEANSTRING="`echo -n "${STRING}" | tr -cd '[:alnum:] [:space:]' | tr '[:space:]' '-'  | tr '[:upper:]' '[:lower:]'`"

奥卡姆剃刀,我想。


1
如果你设置了STRING=$(rm /tmp/*),如果在清理之前echo $STRING,它将执行子shell并删除/tmp/内容...所以你需要在任何echo之前对其进行清理。 - higuita

0
你可以通过 Perl 运行它。
export CLEANSTRING=$(perl -e 'print join( q//, map { s/\\s+/_/g; lc } split /[^\\s\\w]+/, \$ENV{STRING} )')

我在这里使用ksh风格的子shell,但我不完全确定它是否适用于bash。

这就是Shell的好处,你可以使用perl、awk、sed、grep等工具。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接