Pergunta de teste sobre o grep

2

Abaixo está uma questão de teste para um exame prático de LPIC-1 que fiz. A resposta correta é A. Estou realmente deslumbrado com a forma como este é o caso. Se não for um problema, alguém pode me explicar como A é a resposta correta?

int double(int n)
    { /* int arg, int return */
       return n*2;
    }
    char hello(int n)
    { /* int arg, char return */
       printf("hello %i\n", n);
    }
    int five()
    { /* no args, int return */
       return 5;
    }
    int        triple(int n, int other, char nonsense)
    { /* int arg, int return */
       return n*3;
    }

Correctly parsing a C source file requires a full-fledged parser (such as that built into a C compiler). Nonetheless, regular expressions can be used to provide a pretty good approximate descriptions of many program constructs. Which of the following searches will locate at least most of the C functions that accept an int as a first argument, and return an int (and will not produce false positives very often). The exhibit contains a fragment of C code with several annotated matching and non-matching functions (for non-C programmers).

  • A. grep -E "int[ \t]+\w+[ \t]*\([ \t]*int" *.c
  • B. grep -E "^int\w+[A-Za-z_]+\w*\(\w*int" *.c
  • C. grep -E "int.+\([ \t]+int.*\) " *.c
  • D. grep -E "int[ \t]+[A-Za-z_][ \t]+\(int" *.c

Referência: link - especificamente esta questão - 1.3 / 7/1.

    
por user284179 08.08.2018 / 01:02

2 respostas

2

Então "A." é a resposta simplesmente porque é o único que retorna as 2 funções definidas no código de exemplo:

$ grep -E "int[ \t]+\w+[ \t]*\([ \t]*int" sample.c
int double(int n)
    int        triple(int n, int other, char nonsense)

Os outros 3 não retornam nada, se você os tentar. Este funciona porque é capaz de lidar com as duas situações presentes nestas linhas:

int double(int n)
    int        triple(int n, int other, char nonsense)

O grep :

  • int[ \t]+ - corresponde a linhas que começam com int seguido por pelo menos 1 espaço ou tabulação ( \t )
  • \w+ - corresponde a um ou mais caracteres em uma palavra (duplo e triplo)
  • [ \t]* - zero ou mais espaços ou tabulações
  • \([ \t]*int - um parents aberto ( ( ) seguido por zero ou mais espaços ou tabs seguidos pela string int

OBSERVAÇÃO: a questão assume o GNU grep , pois está utilizando \w . Outras implementações de grep não suportam essa notação com sua regex ( -E ), para estas, usar [[:alnum:]] é a melhor escolha. Além disso, uma escolha mais sábia seria [[:blank:]] em vez de [ \t] , já que tecnicamente isso corresponde a espaços, barras invertidas e t como o POSIX requer.

Reescrevendo o "A" responda que esta é uma solução muito mais compatível:

$ grep -E "int[[:blank:]]+[[:alpha:]_][[:alnum:]_]+[[:blank:]]*\([[:blank:]]*int" sample.c

Aqui você pode ver em vermelho o que realmente correspondeu o grep acima:

    
por 08.08.2018 / 04:53
3

Assumindo que quando você fizer o teste, você não pode realmente executar os comandos grep contra os dados de entrada, então você terá que olhar para as expressões e fazer algumas suposições.

Olhando para eles na ordem inversa:

  • D. grep -E "int[ \t]+[A-Za-z_][ \t]+\(int" *.c

    Isso não permite nomes de função maiores que um único caractere ( [A-Za-z_] ) e assume que deve haver pelo menos um espaço, barra invertida ou t entre o nome da função e a lista de argumentos.

    Corresponde int a (int ou int at(int mas não int foo(int .

  • C. grep -E "int.+\([ \t]+int.*\) " *.c

    Isso pressupõe que a lista de argumentos comece com pelo menos um espaço, barra invertida ou t .

    Corresponde int foo( int ou int foo(tint mas não int foo(int .

  • grep -E "^int\w+[A-Za-z_]+\w*\(\w*int" *.c

    Isso não permite nenhum espaço entre o tipo de retorno int e o nome da função, e assume que a definição da função começa no início da linha (o código de exemplo contém algumas definições de função recuadas).

    Corresponde intfoo(int , mas não int foo(int .

  • grep -E "int[ \t]+\w+[ \t]*\([ \t]*int" *.c

    Este é o único que permite uma correspondência em int foo(int , mas também corresponde a nomes de função inválidos, como int 000(int . No entanto, é a melhor expressão regular dos quatro dados.

Note também que esta questão assume o GNU grep para corresponder \w . Com um padrão grep implementation [[:alnum:]_] teria sido melhor para \w e [[:blank:]] deveria ter sido usado no lugar de espaço ou tabulação correspondentes ( [ \t] corresponde a espaço, barra invertida ou t ).

    
por 08.08.2018 / 09:24

Tags