文件夹中字符输出文件列表中的转义星号 (*)
Escaped asterisk (*) in list of characters outputs file in folder
在我的 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=
15 [[ ${#INPUT} -ge $minlen ]] && echo
16 if [[ ${#INPUT} -lt $maxlen ]]; then
17 for c in $chars; do
18 increment $c
19 done
20 fi
21 }
22
23 function showUsage {
24 echo "[=12=] 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 [[ "" = "" ]] && showUsage && exit
41 maxlen=
42 [[ -eq 0 ]] && minlen=$maxlen || minlen=
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
使用单引号代替双引号来包裹您的字符串。您不必转义单引号旁边的任何字符。
最好的方法可能是使用:
set -o noglob
set="* + ?"
for i in $set; do echo $i; done
*
+
?
使用变量时的问题。 noglob
将阻止所有文件 glob 字符扩展。
你不能安全地循环像这样的字符串中的单词列表,而不会产生令人讨厌的通配效果。在你的情况下,它归结为:
a=*
for i in $a; do
echo "$a"
done
您会看到当前目录中的文件已打印出来,因为 for
语句中的(未加引号!恐怖!)$a
扩展为 *
,这将导致 glob到当前目录中的文件列表。
您必须使用其他设计来解决此问题。你很幸运,Bash 很好地支持数组,所以重新设计你的代码以使用数组。例如:
chars=( ° § + \" ç % \& / '(' ')' = \? \' ^ ! £ $ - _ \; , : . \* )
(这定义了 数组 chars
)并循环遍历:
for i in "${chars[@]}"; do
echo "$i"
done
(注意引号)。
下面是对您的代码的重写,以向您展示如何使用数组(我还 fixed/improved 一些其他的小东西):
#!/bin/bash
chars_alpha=( {a..z} )
chars_ALPHA=( {A..Z} )
chars_digit=( {0..9} )
chars_punct=( '°' '§' '+' '"' 'ç' '%' '&' '/' '(' ')' '=' '?' "'" '^' '!' '£' '$' '-' '_' ';' ',' ':' '.' '*' )
increment() {
local input=
(( ${#input} >= minlen )) && printf '%s\n' "$input"
if (( ${#input} < maxlen )); then
for c in "${chars[@]}"; do
increment "$input$c"
done
fi
}
showUsage() {
cat <<EOF
[=13=] 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; }
[[ = +([[:digit:]]) ]] || { showUsage; exit 1; }
((maxlen=10#))
shift
# Check that maxlen is >0 or exit gracefully
((maxlen>0)) || exit 0
if [[ = +([[:digit:]]) ]]; then
((minlen=10#))
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 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' "" ;;
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
不要输出任何东西!
感谢您的所有建议。帮助我解决这个问题的是
set -f
这当然是一个快速修复。但对我来说效果很好。
在我的 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=
15 [[ ${#INPUT} -ge $minlen ]] && echo
16 if [[ ${#INPUT} -lt $maxlen ]]; then
17 for c in $chars; do
18 increment $c
19 done
20 fi
21 }
22
23 function showUsage {
24 echo "[=12=] 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 [[ "" = "" ]] && showUsage && exit
41 maxlen=
42 [[ -eq 0 ]] && minlen=$maxlen || minlen=
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
使用单引号代替双引号来包裹您的字符串。您不必转义单引号旁边的任何字符。
最好的方法可能是使用:
set -o noglob
set="* + ?"
for i in $set; do echo $i; done
*
+
?
使用变量时的问题。 noglob
将阻止所有文件 glob 字符扩展。
你不能安全地循环像这样的字符串中的单词列表,而不会产生令人讨厌的通配效果。在你的情况下,它归结为:
a=*
for i in $a; do
echo "$a"
done
您会看到当前目录中的文件已打印出来,因为 for
语句中的(未加引号!恐怖!)$a
扩展为 *
,这将导致 glob到当前目录中的文件列表。
您必须使用其他设计来解决此问题。你很幸运,Bash 很好地支持数组,所以重新设计你的代码以使用数组。例如:
chars=( ° § + \" ç % \& / '(' ')' = \? \' ^ ! £ $ - _ \; , : . \* )
(这定义了 数组 chars
)并循环遍历:
for i in "${chars[@]}"; do
echo "$i"
done
(注意引号)。
下面是对您的代码的重写,以向您展示如何使用数组(我还 fixed/improved 一些其他的小东西):
#!/bin/bash
chars_alpha=( {a..z} )
chars_ALPHA=( {A..Z} )
chars_digit=( {0..9} )
chars_punct=( '°' '§' '+' '"' 'ç' '%' '&' '/' '(' ')' '=' '?' "'" '^' '!' '£' '$' '-' '_' ';' ',' ':' '.' '*' )
increment() {
local input=
(( ${#input} >= minlen )) && printf '%s\n' "$input"
if (( ${#input} < maxlen )); then
for c in "${chars[@]}"; do
increment "$input$c"
done
fi
}
showUsage() {
cat <<EOF
[=13=] 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; }
[[ = +([[:digit:]]) ]] || { showUsage; exit 1; }
((maxlen=10#))
shift
# Check that maxlen is >0 or exit gracefully
((maxlen>0)) || exit 0
if [[ = +([[:digit:]]) ]]; then
((minlen=10#))
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 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' "" ;;
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
不要输出任何东西!
感谢您的所有建议。帮助我解决这个问题的是
set -f
这当然是一个快速修复。但对我来说效果很好。