在我的Bash脚本的最开始,我传递了一组这样的字符:
#!/bin/bash
set0="0 1 2 3 4 5 6 7 8 9"
set1="° § + \" ç % & / ( ) = ? ' ^ ! £ $ - _ ; , : . *"
该脚本将每个字符与其他字符组合在一起,以便与n
的长度进行所有可能的组合。
正如您在上面的set1
中所看到的,我必须逃避引用"
字符。我现在的问题是,我也必须逃避星号*
。但我无法弄清楚如何。
到目前为止这无效:
#!/bin/bash
set1="° § + \" ç % & / ( ) = ? ' ^ ! £ $ - _ ; , : . \*"
它回应\*
。如果我没有使用反斜杠*
转义星号\
,则脚本会一直回显当前目录中的所有文件。
你知道如何成功逃脱星号*
吗?
这是整个剧本:
8 chars0="a b c d e f g h i j k l m n o p q r s t u v w x y z"
9 chars1="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
10 chars2="0 1 2 3 4 5 6 7 8 9"
11 chars3="° § + \" ç % & / ( ) = ? ' ^ ! £ $ - _ ; , : . *"
12
13 function increment {
14 INPUT=$1
15 [[ ${#INPUT} -ge $minlen ]] && echo $1
16 if [[ ${#INPUT} -lt $maxlen ]]; then
17 for c in $chars; do
18 increment $1$c
19 done
20 fi
21 }
22
23 function showUsage {
24 echo "$0 MAXLEN [MINLEN] [a [A [n [p]]]]"
25 echo
26 echo " MAXLEN integer Maximum lenght, or specific lengt if MINLEN is omitted"
27 echo " MINLEN integer Minimum lenght, equals MAXLEN if omitted"
28 echo ""
29 echo " characters:"
30 echo " a lower case a-z"
31 echo " A Uppercase A-Z"
32 echo " n numeric 0-9"
33 echo " p punctuation . ?"
34 }
35
36
37
38
39 ## argument handler
40 [[ "$1" = "" ]] && showUsage && exit
41 maxlen=$1
42 [[ $2 -eq 0 ]] && minlen=$maxlen || minlen=$2
43
44
45 for arg in "$@"; do
46 case $arg in
47 a) chars="$chars $chars0" ;;
48 A) chars="$chars $chars1" ;;
49 n) chars="$chars $chars2" ;;
50 p) chars="$chars $chars3" ;;
51 esac;
52 done
53
54 #fallback
55 [[ "$chars" = "" ]] && chars="$chars0"
56
57
58
59 ## kickof
60
61 for i in $chars; do
62 increment $i
63 done
答案 0 :(得分:0)
最好的方法是使用:
set -o noglob
set="* + ?"
for i in $set; do echo $i; done
*
+
?
使用变量时的问题。 noglob
将阻止所有文件glob字符扩展。
答案 1 :(得分:0)
你不能安全地循环这样的字符串中的单词列表,而不会有令人讨厌的globbing效果。在你的情况下,它归结为:
a=*
for i in $a; do
echo "$a"
done
你会看到当前目录中的文件被打印出来,因为$a
语句中的(未引用的!恐怖!)for
会扩展为*
当前目录中的文件列表。
您必须使用其他设计来解决此问题。你很幸运,Bash非常支持数组,所以重新设计代码以使用数组。例如:
chars=( ° § + \" ç % \& / '(' ')' = \? \' ^ ! £ $ - _ \; , : . \* )
(这定义了数组 chars
)并循环遍历:
for i in "${chars[@]}"; do
echo "$i"
done
(观察引号)。
下面是对代码的重写,以向您展示如何使用数组(我也修复/改进了其他一些小东西):
#!/bin/bash
chars_alpha=( {a..z} )
chars_ALPHA=( {A..Z} )
chars_digit=( {0..9} )
chars_punct=( '°' '§' '+' '"' 'ç' '%' '&' '/' '(' ')' '=' '?' "'" '^' '!' '£' '$' '-' '_' ';' ',' ':' '.' '*' )
increment() {
local input=$1
(( ${#input} >= minlen )) && printf '%s\n' "$input"
if (( ${#input} < maxlen )); then
for c in "${chars[@]}"; do
increment "$input$c"
done
fi
}
showUsage() {
cat <<EOF
$0 MAXLEN [MINLEN] [a] [A] [n] [p]
MAXLEN integer Maximum lenght, or specific lengt if MINLEN is omitted
MINLEN integer Minimum lenght, equals MAXLEN if omitted
characters:
a lower case a-z
A Uppercase A-Z
n numeric 0-9
p punctuation . ? etc.
EOF
}
## argument handler
(($#)) || { showUsage; exit 1; }
[[ $1 = +([[:digit:]]) ]] || { showUsage; exit 1; }
((maxlen=10#$1))
shift
# Check that maxlen is >0 or exit gracefully
((maxlen>0)) || exit 0
if [[ $1 = +([[:digit:]]) ]]; then
((minlen=10#$1))
shift
else
((minlen=maxlen))
fi
# Check that minlen<=maxlen otherwise swap them
if ((minlen>maxlen)); then
((temp=minlen,minlen=maxlen,maxlen=temp))
fi
chars=()
while (($#)); do
case $1 in
(a) chars+=( "${chars_alpha[@]}" ); chars_alpha=() ;;
(A) chars+=( "${chars_ALPHA[@]}" ); chars_ALPHA=() ;;
(n) chars+=( "${chars_digit[@]}" ); chars_digit=() ;;
(p) chars+=( "${chars_punct[@]}" ); chars_punct=() ;;
(*) printf >&2 'Ignored arguments %s\n' "$1" ;;
esac
shift
done
#fallback
(( ${#chars[@]} )) || chars=( "${chars_alpha[@]}" )
#kick off!
increment
其中一项修复包括使用printf
代替echo
。使用echo
时,您的代码会被破坏,因为字符串:
-e
-n
-E
永远不会被打印出来!请参阅help echo
以了解原因。也可以自己尝试一下:
echo -e
echo -n
echo -E
不输出任何内容!
答案 2 :(得分:0)
感谢您的所有建议。帮助我解决这个问题的是
set -f
当然,这是一个快速解决方案。但它对我来说效果很好。
答案 3 :(得分:-1)
使用单引号包装字符串而不是双引号。您不必在单引号旁边转义任何字符。