文件夹中的字符输出文件列表中的转义星号 (*)

问题描述 投票:0回答:4

在 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
bash
4个回答
0
投票

感谢您的所有建议。帮助我解决这个问题的是

set -f

这当然是一个快速解决方案。但对我来说效果很好。


0
投票

最好的方法可能是使用:

set -o noglob
set="* + ?"
for i in $set; do echo $i; done
*
+
?

使用变量时的问题。

noglob
将阻止所有文件全局字符扩展。


0
投票

您无法安全地循环像这样的字符串中的单词列表,而不产生令人讨厌的通配符效果。就您而言,归结为:

a=*
for i in $a; do
    echo "$a"
done

您将看到当前目录中的文件被打印,因为

$a
语句中的(未加引号!恐怖!)
for
扩展为
*
,它将全局显示当前目录中的文件列表。

您必须使用其他设计来解决此问题。你很幸运,Bash 很好地支持数组,所以重新设计你的代码以使用数组。例如:

chars=( ° § + \" ç % \& / '(' ')' = \? \' ^ ! £ $ - _ \; , : . \* )

(这定义了 array

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

不输出任何内容!


-1
投票

使用单引号代替双引号来包裹字符串。您不必转义单引号之外的任何字符。

© www.soinside.com 2019 - 2024. All rights reserved.