Как вы можете сказать, какие персонажи в каких классах персонажей? - PullRequest
8 голосов
/ 06 июня 2019

Мы часто видим, как люди задают вопросы о том, почему их строка не соответствует их регулярному выражению, и иногда ответ сводится к тому, что они ожидают, что персонаж будет частью класса символов, если это не так, или они пытаются использовать сокращение для класс символов (например, \d для [[:digit:]]), который существует в каком-либо другом инструменте, но просто не является частью языка awk. Имея это в виду, я создаю канонический ответ на вопрос о том, какие персонажи существуют и какие классы персонажей в awk.

1 Ответ

8 голосов
/ 06 июня 2019

Следующий скрипт сгенерирует набор символов в каждом классе символов (плюс расширения \ s, \ S, \ w и \ W, если ваш awk их поддерживает) для вашей локали для символов в числовом диапазоне 0- 127, как указано в первой таблице на http://www.asciitable.com/ и https://en.wikipedia.org/wiki/ASCII. Для символа горизонтальной табуляции в качестве вывода на print "\t" первая ссылка использует TAB, а другой HT в качестве сокращения - я предпочитаю TAB, поэтому я использовал это ниже. Они оба используют Space для представления вывода символа с помощью print " ", поэтому я также сделал это ниже, хотя я чаще называю его "пустым символом":

$ cat prtCharClasses.awk
# From the gawk manual, https://www.gnu.org/software/gawk/manual/gawk.html#Bracket-Expressions:
#   [:alnum:]   Alphanumeric characters
#   [:alpha:]   Alphabetic characters
#   [:blank:]   Space and TAB characters
#   [:cntrl:]   Control characters
#   [:digit:]   Numeric characters
#   [:graph:]   Characters that are both printable and visible (a space is printable but not visible, whereas an ‘a’ is both)
#   [:lower:]   Lowercase alphabetic characters
#   [:print:]   Printable characters (characters that are not control characters)
#   [:punct:]   Punctuation characters (characters that are not letters, digits, control characters, or space characters)
#   [:space:]   Space characters (these are: space, TAB, newline, carriage return, formfeed and vertical tab)
#   [:upper:]   Uppercase alphabetic characters
#   [:xdigit:]  Characters that are hexadecimal digits
#   \s          Matches any whitespace character. Think of it as shorthand for ‘[[:space:]]’.
#   \S          Matches any character that is not whitespace. Think of it as shorthand for ‘[^[:space:]]’.
#   \w          Matches any word-constituent character—that is, it matches any letter, digit, or underscore. Think of it as shorthand for ‘[[:alnum:]_]’.
#   \W          Matches any character that is not word-constituent. Think of it as shorthand for ‘[^[:alnum:]_]’.

BEGIN {
    asciiMax = (asciiMax == "" ? 127 : asciiMax)

    numClasses = split("\
        [[:alpha:]]     \
        [[:digit:]]     \
        [[:alnum:]]     \
        [[:lower:]]     \
        [[:upper:]]     \
        [[:xdigit:]]    \
        [[:punct:]]     \
        [[:cntrl:]]     \
        [[:graph:]]     \
        [[:print:]]     \
        [[:blank:]]     \
        [[:space:]]     \
        \\s             \
        \\S             \
        \\w             \
        \\W             \
    ", classes)

    # Map the control chars and white space in the 0-127 range to
    # their abbreviations to make them visible in the output:
    split("NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US Space", map)
    map[128] = "DEL"

    for (asciiNr=0; asciiNr<=asciiMax; asciiNr++) {
        char = sprintf("%c", asciiNr)
        chars[++numChars] = char
    }

    for (classNr in classes) {
        class = classes[classNr]
        for (charNr in chars) {
            char = chars[charNr]
            if ( char ~ class ) {
                classChars[classNr,charNr]
            }
        }
    }

    for (classNr=1; classNr<=numClasses; classNr++) {
        class = classes[classNr]
        printf "%-12s =", class
        for (charNr=1; charNr<=numChars; charNr++) {
            if ( (classNr,charNr) in classChars ) {
                char = chars[charNr]
                printf " %s", (charNr in map ? map[charNr] : char)
            }
        }
        print ""
    }
}

Вот вывод для символов 0-127 в локали C, если у вас другая локаль, тогда выходные данные будут другими, поэтому запустите приведенный выше скрипт, чтобы увидеть, что находится в вашей локали:

$ awk -f prtCharClasses.awk file
[[:alpha:]]  = 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 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
[[:digit:]]  = 0 1 2 3 4 5 6 7 8 9
[[:alnum:]]  = 0 1 2 3 4 5 6 7 8 9 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 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
[[:lower:]]  = 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
[[:upper:]]  = 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
[[:xdigit:]] = 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
[[:punct:]]  = ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
[[:cntrl:]]  = NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US DEL
[[:graph:]]  = ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~
[[:print:]]  = Space ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~
[[:blank:]]  = TAB Space
[[:space:]]  = TAB LF VT FF CR Space
\s           = TAB LF VT FF CR Space
\S           = NUL SOH STX ETX EOT ENQ ACK BEL BS SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~ DEL
\w           = 0 1 2 3 4 5 6 7 8 9 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 _ 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
\W           = NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US Space ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~ DEL

Обратите внимание, что \s, \S, \w и \W - это расширения, доступные только в некоторых инструментах, например, GNU awk. \d и \D выше не представлены - это расширения, доступные в некоторых инструментах, которые поддерживают PCRE как сокращение для [:digit:], но не включают ни одного варианта awk. Если вы хотите сокращение для [:digit:], тогда [0-9] представляется переносимым во всех локалях, но я исправляюсь.

Если вам нужно увидеть символы за номером 127, вы можете установить asciiMax в командной строке, например ::

$ awk -v asciiMax=255 -f prtCharClasses.awk
[[:alpha:]]  = 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 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 ª µ º À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ
[[:digit:]]  = 0 1 2 3 4 5 6 7 8 9
[[:alnum:]]  = 0 1 2 3 4 5 6 7 8 9 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 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 ª µ º À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ
[[:lower:]]  = 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 µ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ
[[:upper:]]  = 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 À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ
[[:xdigit:]] = 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
[[:punct:]]  = ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ ¡ ¢ £ ¤ ¥ ¦ § ¨ © « ¬ ® ¯ ° ± ² ³ ´ ¶ · ¸ ¹ » ¼ ½ ¾ ¿ × ÷
[[:cntrl:]]  = NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US DEL                                
[[:graph:]]  = ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
[[:print:]]  = Space ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
[[:blank:]]  = TAB Space  
[[:space:]]  = TAB LF VT FF CR Space  
\s           = TAB LF VT FF CR Space  
\S           = NUL SOH STX ETX EOT ENQ ACK BEL BS SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ 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 [ \ ] ^ _ ` 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 { | } ~ DEL                                 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
\w           = 0 1 2 3 4 5 6 7 8 9 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 _ 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 ª µ º À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ø ù ú û ü ý þ ÿ
\W           = NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US Space ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~ DEL                                   ¡ ¢ £ ¤ ¥ ¦ § ¨ © « ¬ ­ ® ¯ ° ± ² ³ ´ ¶ · ¸ ¹ » ¼ ½ ¾ ¿ × ÷
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...