Closed FernandaMatt closed 1 year ago
'
and Double quotes "
From the bash manual:
3.1.2.2 Single Quotes Enclosing characters in single quotes (
'
) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash. 3.1.2.3 Double Quotes Enclosing characters in double quotes ("
) preserves the literal value of all characters within the quotes, with the exception of$
, `,\
, and, when history expansion is enabled,!
. The characters$
and ` retain their special meaning within double quotes (see Shell Expansions). The backslash retains its special meaning only when followed by one of the following characters:$
, `,"
,\
, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an!
appearing in double quotes is escaped using a backslash. The backslash preceding the!
is not removed.
In summary, single quotes always maintain the literal values of the characters enclosed, no matter what. Meanwhile double quotes don't preserve the literal values of $
, `, \
, and, when history expansion is enabled, !
(but we don't need to handle the characters that are not in the list of special characters mentioned in the subject). We can use \
scapes with double, but not with single quotes, the \
will only function as a scape, if it is followed by a special character, otherwise it will maintain it's litteral value.
:brazil:
Em resumo, os caracteres em asplas simples sempre manterão seu valor literal, já as aspas duplas não preservarão o valor dos caracteres especiais $
, `, \
e !
quando a expansão de histórico estiver habilitada (mas só precisamos nos preocupar com os caracteres exigidos no subject list). Por exemplo, nós podemos acessar o valor de variáveis de ambiente com $ENVAR
entre aspas duplas, ou usar scape com \
, mas entre aspas simples, não, eles manterão seu valor literal.
Some bash tests:
feffa@fcaetano42:~$ echo "test $PATH"
test /usr/local/bin:/usr/bin:/bin:/usr/games
feffa@fcaetano42:~$ echo 'test $PATH'
test $PATH
feffa@fcaetano42:~$ echo 'test print a single quote ' between single quotes'
> ...
> heredoc
> ... '
test print a single quote between single quotes
...
heredoc
...
feffa@fcaetano42:~$ echo "test print a single quote ' between double quotes"
test print a single quote ' between double quotes
feffa@fcaetano42:~$ echo "test print a double quote " between double quotes"
> ...
> heredoc
> ... "
test print a double quote between double quotes
...
heredoc
...
feffa@fcaetano42:~$ echo "test print a double quote scaped \" between double quotes"
test print a double quote scaped " between double quotes
feffa@fcaetano42:~$ echo "test print a single quote scaped \' between double quotes"
test print a single quote scaped \' between double quotes
feffa@fcaetano42:~$ echo 'test print a single quote scaped \' between single quotes'
> ...
> heredoc
> ... '
test print a single quote scaped \ between single quotes
...
heredoc
...
feffa@fcaetano42:~$ echo 'test print a single quote in double quotes "'" between single quotes'
> ...
> heredoc
> ... '
> ... "
test print a single quote in double quotes " between single quotes'
...
heredoc
... '
...
feffa@fcaetano42:~$ echo "test print a double quote in single quotes '"' between double quotes"
> ...
> heredoc
> ... '
test print a double quote in single quotes ' between double quotes"
...
heredoc
...
|
A pipe in Bash takes the standard output of one process and passes it as standard input into another process.
:brazil:
Um pipe redirecionará a saída padrão de um processo e passará isso como entrada para um outro processo.
Some bash tests:
feffa@fcaetano42:~$ echo "test pipe" | cat > test.txt
feffa@fcaetano42:~$ cat test.txt
test pipe
feffa@fcaetano42:~$ ls | wc -l
11
feffa@fcaetano42:~$ ls|wc -l
11
feffa@fcaetano42:~$ ls |wc -l
11
feffa@fcaetano42:~$ ls| wc -l
11
feffa@fcaetano42:~$ ls | wc -l
11
feffa@fcaetano42:~$ ls
42 Documents mini-bash Pictures Templates Videos
Desktop Downloads Music Public test.txt
feffa@fcaetano42:~$ ls | grep D | wc -l
3
feffa@fcaetano42:~$ ls | grep D| wc -l
3
feffa@fcaetano42:~$ ls |grep D| wc -l
3
feffa@fcaetano42:~$ ls |grep D|wc -l
3
feffa@fcaetano42:~$ ls|grep D|wc -l
3
feffa@fcaetano42:~$ ls|grep D |wc -l
3
feffa@fcaetano42:~$ ls | grep D |
> heredoc ...
bash: heredoc: command not found
:warning: Unlike flags and most command and functions inputs/arguments, pipes |
work with "wrong spacing", as seen in the tests above. See the behavior in the tests.
When a |
is at the end of the command line, heredoc starts for the user to complete the command. When a |
is at the beginning of a command line, bash returns a syntax error.
If the first command of a pipe line fails it doesn't stop the execution of the rest of the line.
:brazil:
:warning: Diferente de flags e inputs/argumentos de funções e comandos que são separados no terminal por espaço, os pipes são reconhecidos independente disso. Observar nos testes. Quando um pipe encerra uma linha de comando, o heredoc é iniciado para esperar que o usuário entre com a próxima instrução. Quando um |
está no início de uma linha de comando, o bash retorna um erro de sintaxe.
Se o primeiro comando de uma sequência de pipes falha, isso não interrompe a execução do restante da sequência.
feffa@fcaetano42:~/42/projetos$ echo test
test
feffa@fcaetano42:~/42/projetos$ | echo test
bash: syntax error near unexpected token `|'
feffa@fcaetano42:~/42/projetos$ |echo test
bash: syntax error near unexpected token `|'
feffa@fcaetano42:~/42/projetos$ | echo test
bash: syntax error near unexpected token `|'
feffa@fcaetano42:~/42/projetos$ | echo test
bash: syntax error near unexpected token `|'
feffa@fcaetano42:~/42/projetos$ a | echo test
test
bash: a: command not found
>
, <
, >>
and <<
>
:
This symbol, known as the file redirection operator, is typically used to redirect the contents of a command/file to another by overwriting it. Mind you; it overwrites it !
:brazil:
Símbolo de redirecionamento de arquivo, normalmente é usado para redirecionar o conteúdo de um arquivo ou comando para outro, sobrescrevendo o destino.
feffa@fcaetano42:~$ cat test.txt
test pipe
feffa@fcaetano42:~$ echo "test redirects" > test.txt
feffa@fcaetano42:~$ cat test.txt
test redirects
When we write command > file.txt
it is equivalent to writing command 1> file.txt
. The number is the file descriptor from the file we are redirecting. 1 is the default and is the standard output (0 is standard input, and 2 standard error). But we can redirect from the standard error as well.
:brazil:
Quando escrevemos command > file.txt
é o mesmo que escrevermos command 1> file.txt
. O número é o file descriptor do arquivo que estamos redirecionando. 1 é o padrão e é o fd do standard output (saída padrão) (0 é standard input e 2 standard error) Nós podemos redirecionar a saída do standard error, ao invés do standard output usando 2>
.
feffa@fcaetano42:~$ mcat test.txt 1> test2.txt
bash: mcat: command not found
feffa@fcaetano42:~$ mcat test.txt > test2.txt
bash: mcat: command not found
feffa@fcaetano42:~$ mcat test.txt 2> test2.txt
feffa@fcaetano42:~$ cat test2.txt
bash: mcat: command not found
<
:
The symbol <
is used for input redirection. Files, for example, can be used as input. However, in this case, the input redirection is a read-only redirection.
:brazil:
O símbolo <
é usado para redirecionamento de input. Podemos, por exemplo, usar arquivos como inputs. No entanto, nesse caso o redirecionamento da entrada/arquivo é reado-only, ou seja, apenas escrita, não temos permissão de alterar o arquivo.
feffa@fcaetano42:~$ cat < test.txt
test redirects 2
//In this case, the file.txt is taken as the input, and the cat command then cats it out.
>>
:
The append >> operator adds the output to the existing content instead of overwriting it. This allows you to redirect the output from multiple commands to a single file.
:brazil:
O operador append >>
, funciona também para redirecionamento de output, como o >
, no entanto, ele adiciona o output ao final do arquivo, ao invés de sobrescrever seu conteúdo. Isso permite que se faça o redirecionamento de vários comandos consecutivos em um único arquivo.
feffa@fcaetano42:~$ date > test.txt
feffa@fcaetano42:~$ cat test.txt
Fri 17 Feb 2023 09:15:08 PM -03
feffa@fcaetano42:~$ hostname >> test.txt
feffa@fcaetano42:~$ uname -r >> test.txt
feffa@fcaetano42:~$ cat test.txt
Fri 17 Feb 2023 09:15:08 PM -03
fcaetano42
5.10.0-21-amd64
<<
:
Use: <<MARKER
Known as the here-document redirection operator. This operator instructs bash to read the input from stdin until a line containing only the delimiter MARKER
is found. At this point bash passes the all the input read so far to the stdin of the command.
:brazil:
Uso: << MARKER
Conhecido como operador de redirecionamento de here-document. Esse operador instrui o bash a ler a entrada até que uma linha contendo somente o delimitador MARKER
seja inserida. Nesse momento o bash reconhece o final da linha de comando e a mesma é repassada como entrada do comando.
feffa@fcaetano42:~$ sed 's|http://||' http://url1.com
sed: can't read http://url1.com: No such file or directory
feffa@fcaetano42:~$ sed 's|http://||' <<EOL
> http://url1.com
> EOL
url1.com
feffa@fcaetano42:~$
When the delimiter is quoted no parameter expansion and/or command substitution is done by the shell. (Not sure if we need to implement that in our mini-shell)
:brazil:
Quando o delimitador está entre aspas, nenhuma expansão de parametros e/ou comandos de substituição é feito pela shell. (Não sei se precisamos implementar isso)
feffa@fcaetano42:~$ cat <<STOP
> Current directory: $PWD
> Current user: $(whoami)
> STOP
Current directory: /home/feffa
Current user: feffa
feffa@fcaetano42:~$ cat <<"STOP"
> Current directory: $PWD
> Current user: $(whoami)
> STOP
Current directory: $PWD
Current user: $(whoami)
:question: Is better to create a separate token to >>
and <<
, or to handle two <
or >
consecutive tokens after? I think I would create a separate token, but it's worth to ask a few people and see what is better.
:warning: Unlike flags and most command and functions inputs/arguments, redirects work with "wrong spacing", as seen in the tests above. See the behavior in the tests. When a redirect is at the end of a command line, the shell returns a syntax error.
:brazil:
:question: É melhor criar um token separado para >>
e <<
, ou tratar dois <
or >
tokens consecutivos depois no parser? A princípio me parece melhor criar os tokens, mas talvez seja melhor trocar uma ideia com quem já fez a tokenização.
:warning: Diferente de flags e inputs/argumentos de funções e/ou comandos que são separados no terminal por espaço, os redirects são reconhecidos independente disso. Observar nos testes. Quando um redirect encerra uma linha de comando, a shell retorna um erro de sintaxe.
feffa@fcaetano42:~/42/projetos$ cat $HOSTNAME
cat: fcaetano42: No such file or directory
feffa@fcaetano42:~/42/projetos$ cat $HOSTNAME >
bash: syntax error near unexpected token `newline'
feffa@fcaetano42:~/42/projetos$ cat $HOSTNAME <
bash: syntax error near unexpected token `newline'
feffa@fcaetano42:~/42/projetos$ cat $HOSTNAME <<
bash: syntax error near unexpected token `newline'
feffa@fcaetano42:~/42/projetos$ cat $HOSTNAME >>
bash: syntax error near unexpected token `newline'
$
The $
is a special character that can be used with variables to expand their values. In the mini-shell project we will implement the $
functionalities to handle environment variables and the $?
which should expand to the exit status of the most recently executed foreground pipe line. The command env
shows the environment variables.
🇧🇷
O caractere especial $
pode ser usado para retornar o valor de variáveis, expandido-as ao seu valor em uma cadeia de string, por exemplo. No projeto da mini-shell nós iremos implementar a funcionalidade desse caractere para lidar com variáveis de ambiente e com $?
, que deve retornar o status de saída (exit status) do pipe mais recente executado em primeiro plano.
$ENVVAR
:
In the case of using $
with enviroment variables $ENVVAR
should expand to the value of the environment variable. The command env
can be used to show the environment variables.
🇧🇷
No uso de $
com variáveis de ambiente, a cadeia $ENVVAR
deveria expandir para o valor da variável de ambiente ENVVAR
. O comando env
pode ser usado para mostrar as variáveis de ambiente.
feffa@fcaetano42:~$ $OLDPWD
bash: /home/feffa/42/projetos/mini-bash: Is a directory
feffa@fcaetano42:~$ echo $USER > test2.txt
feffa@fcaetano42:~$ cat test2.txt
feffa
feffa@fcaetano42:~$ echo $HOME >> test2.txt
feffa@fcaetano42:~$ cat test2.txt
feffa
/home/feffa
$?
:
It should expand to the exit status of the most recently executed foreground pipe line. The exit status of a command is an integer number returned by each Linux command when it terminates normally or abnormally. 0 exit status means the command was successful without any errors, and a non-zero (1-255 values) exit status means command was failure. The Linux man pages stats the exit statuses of each command. The special shell variable $?
can be used to get the exit status of the previously executed command.
🇧🇷
Deve retornar o status de saída (exit status) do pipe mais recente executado em primeiro plano. O status de saída de um comando é número inteiro retornado por cada comando comando Linux quando o mesmo se encerra, de forma normal ou abrupta. O status 0 significa que o comando terminou a execução com sucesso, sem erros, enquanto um status diferente de 0 (entre 1 e 255), significa que houve alguma falha ou comportamento inesperado durante a execução. Os manuais do Linux especificam o status de saída para cada comando. Para exibir o status de saída do último comando, podemos utilizar $?
.
feffa@fcaetano42:~$ echo test
test
feffa@fcaetano42:~$ $?
bash: 0: command not found
feffa@fcaetano42:~$ non-existing-command
bash: non-existing-command: command not found
feffa@fcaetano42:~$ $?
bash: 127: command not found
feffa@fcaetano42:~$ true
feffa@fcaetano42:~$ $?
bash: 0: command not found
feffa@fcaetano42:~$ false
feffa@fcaetano42:~$ $?
bash: 1: command not found
feffa@fcaetano42:~$ true | false
feffa@fcaetano42:~$ $?
bash: 1: command not found
feffa@fcaetano42:~$ false | true
feffa@fcaetano42:~$ $?
bash: 0: command not found
//0: succesfully/true exit status
//1: false exit status
//127: command not found exit status
There is an internal Bash variable called PIPESTATUS
; it’s an array that holds the exit status of each command in your last foreground pipeline of commands.
🇧🇷
Existe uma variável interna do Bash chamada PIPESTATUS
; é um array que guarda as informações do status de saída de cada comando da sua última linha de pipes executada em primeiro plano.
feffa@fcaetano42:~$ false | true | false | non-existing-command
bash: non-existing-command: command not found
feffa@fcaetano42:~$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"
1 0 1 127
References
https://www.baeldung.com/linux/pipe-output-to-function https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash https://www.gnu.org/software/bash/manual/html_node/Quoting.html https://unix.stackexchange.com/questions/503013/what-is-the-difference-between-the-and-quotes-in-th https://linuxhint.com/bash_pipe_tutorial/ https://www.redhat.com/sysadmin/redirect-operators-bash https://www.gnu.org/software/bash/manual/html_node/Redirections.html https://linuxhint.com/redirection-operators-bash/ https://linuxize.com/post/bash-heredoc/ https://bash.cyberciti.biz/guide/The_exit_status_of_a_command https://www.cyberciti.biz/faq/unix-linux-bash-find-out-the-exit-codes-of-all-piped-commands/ https://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another/73180#73180 https://stackoverflow.com/questions/1221833/pipe-output-and-capture-exit-status-in-bash
Todo
|
(1)>
(2)<
(3)>>
(4)<<
(5)"
(6)'
(7)cat Makefile |. wc -l. >> " temp.txt ' " (0) (0). (1) (0). (0) (2) (3) (0) (4) (3)
0 -> word 1 -> pipe 2 -> redirect
English
Work in Progress
Example
Português
Work in Progress
A função tokenize recebe como entrada uma string e retorna uma lista de tokens, onde cada token tem um tipo (palavra, pipe, redirecionamento ou aspas) e um valor (o conteúdo da palavra, pipe, redirecionamento ou aspas).
Este código é um exemplo de um lexer simples escrito em C, que lê uma sequência de entrada de caracteres e produz uma lista de tokens com informações sobre o tipo e a palavra correspondente a cada token.
O processo de criação do código envolve a definição de uma estrutura de dados de token, a implementação de uma função de lexer para analisar a entrada de caracteres e gerar os tokens correspondentes, e uma função de impressão de tokens para exibir os resultados na saída.
A função de lexer usa um loop para percorrer a entrada de caracteres, identificar o tipo de cada token com base em regras simples (como caracteres especiais ou aspas), criar um novo token para cada sequência de caracteres que corresponde a um token, e encadear os tokens na lista de tokens.
A função de impressão de tokens apenas percorre a lista de tokens e imprime as informações de tipo e palavra para cada token na saída.