"Erro de sintaxe próximo ao token inesperado" após editar .bashrc

11

Estou tentando acessar a área de transferência, mas quando entro source ~/.bashrc no terminal, recebo este erro:

bash: /home/taran/.bashrc: line 2: syntax error near unexpected token ('
bash: /home/taran/.bashrc: line 2:alias pbpaste='xclip -selection 
clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells

Tentei fazer o tutorial da resposta de Gary Woodfine ao Command Line Clipboard Access .

A saída de cat ~/.bashrcé:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    # We have color support; assume it's compliant with Ecma-48
    # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
    # a case would tend to support setf rather than setaf.)
    color_prompt=yes
    else
    color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

Isso está no Ubuntu 19.04. Alguém pode me ajudar a descobrir como corrigir isso?

Taran
fonte

Respostas:

16

A ressalva está na segunda linha:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells.

Isso deve ser:

alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'
# ~/.bashrc: executed by bash(1) for non-login shells.

Parece que você esqueceu de clicar Enterdepois de inserir o segundo alias, o que resultou em # ~/.bash...seguir diretamente sua aliasdefinição na mesma linha. Sem um espaço anterior, # ~/.bash...não poderia ser interpretado como um comentário do shell, mas como parte do argumento do aliascomando.

Também recomendo colocar aliases no arquivo ~/.bash_aliasesque será originado quando ~/.bashrcfor executado, para que você não precise editar ~/.bashrce, eventualmente, estragar tudo.

Se você insistir em colocar aliases ~/.bashrc, adicione-os no final do arquivo.

Para uma visão mais aprofundada desse tópico, consulte a excelente resposta de Eliah à sua pergunta.

mook765
fonte
6
Esta resposta seria muito melhor se você explicasse por que a correção funciona #
Andy
Obrigado! Btw, mesmo se alguém optar por não seguir o meu conselho de colocar os apelidos em algum lugar após a verificação da interatividade, eu recomendo que # ~/.bashrc: executed by bash(1) for non-login shells.seja mantida como a primeira linha. Não há motivo técnico para forçá-lo a aparecer primeiro (ou mesmo). Mas é um comentário documentando o arquivo inteiro. Portanto, é bastante confuso para os leitores humanos que apareçam após outro código. Entendo que você não queira mudar isso, principalmente porque o OP aceitou essa resposta como era. (Eu acho que a edição para esse ou apenas deixá-lo são ambos razoável sob as circunstâncias.)
Elias Kagan
'preseed' - você quis dizer 'preceder'?
26719 Michael Harvey
20

O mook765 está totalmente correto sobre a causa do problema, e a solução proposta nessa resposta corrige o erro de sintaxe, mas eu recomendo que você o resolva de uma maneira diferente.

É bom colocar definições de alias .bashrc, mas é melhor não colocá-las - ou nada - no topo desse arquivo.

Nós tendemos a pensar .bashrccomo sendo originados apenas por shells interativos, mas esse não é realmente o caso. Os shells remotos não interativos ( se o bash os identificar como tal ) também serão fonte .bashrc. É por isso que o padrão .bashrc1 do Ubuntu contém este código: 2

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Basicamente, tudo o que você inserir .bashrc, incluindo, sem limitação, as definições de alias, deve ir para algum lugar abaixo disso. Você só deve colocar seu próprio código acima desse código se tiver um motivo claro para fazê-lo, o que é raro.

Você pode colocar suas definições de alias em qualquer lugar abaixo desse código , embora eu sugira colocá-las no final do arquivo. Ou você pode preferir colocá-los perto de algumas das definições de alias existentes no arquivo. Ou você pode preferir colocá-los em um arquivo separado ~/.bash_aliases, que você pode criar se ele não existir. 3 Qualquer uma dessas opções é boa.

Aqui está um dos exemplos mais comuns dos efeitos bizarros e inesperados, colocando o próprio código acima da verificação de interatividade. Esse problema em particular ocorre quando o código produz saída, o que não deve acontecer a partir de uma definição de alias. (O alias, quando usado, pode, obviamente, expandir-se para um comando que produz saída, mas uma definição de alias sintaticamente correta não deve produzir saída, a menos que a -popção seja passada para alias.) Não espero que as definições de alias usualmente causem problemas, mesmo que executado em shells não interativos. Os shells não interativos não executam a expansão do alias por padrão de qualquer maneira (embora isso seja apenas um padrão). No entanto, se eles acabarem produzindo efeitos inesperados, é provável que ninguém pense em verificar isso.

Esse é apenas um motivo fraco para evitar colocar definições de alias acima do check-in de interatividade .bashrc. No entanto, como não há absolutamente nenhum benefício em fazê-lo em comparação com colocá-los em qualquer outro lugar do arquivo, recomendo seguir a abordagem geral de colocar apenas o código acima para verificar se você pretende executar deliberadamente em shells remotos não interativos.


O outro aspecto interessante disso é por que este foi um erro de sintaxe:

alias pbpaste='xclip -selection clipboard -o'# ~/.bashrc: executed by bash(1) for non-login shells.

#inicia comentários, que têm permissão para seguir comandos. No entanto, o #caractere não tem o efeito de iniciar um comentário quando ele aparece em uma palavra maior, exceto como o primeiro caractere da palavra. (Nesse sentido, "palavra" inclui itens como pbpaste='xclip -selection clipboard -o'#, devido à citação .) O texto a seguir, que foi planejado como um comentário, é considerado como argumento adicional ao aliasbuiltin. Mas ocorre um erro ao analisá-los, devido à presença inesperada de (, que tem um significado especial para o shell, mas que não faz sentido nesse contexto. O efeito é que o aliasbuilt-in realmente nunca é executado, e você recebe um erro de sintaxe.

Portanto, seria realmente possível corrigir o erro de sintaxe com uma edição de um caractere , colocando um espaço entre os caracteres 'e #nessa linha. Mas, como detalhado acima, recomendo ir mais longe e mover as definições de alias muito mais abaixo no arquivo.


1 O padrão.bashrcno Ubuntu pode ser visualizado em/etc/skel/.bashrc, desde que você não tenha modificado esse arquivo. Isso é copiado no diretório inicial de um usuário quando o usuário é criado. Como muitos arquivos no Ubuntu, esse arquivo é minimamente alterado do Debian, a distribuição da qual o Ubuntu é derivado. Os conselhos neste post se aplicam ao Bash no Debian e no Ubuntu, mas não necessariamente se aplicam sem modificações ao Bash em todos os sistemas GNU / Linux.

2 Também é possível , embora raro, iniciarbashcomo um shell de logon não interativo. Como conchas de login interativas, essas fontes de shell são~/.profileautomaticamente e o padrão~./profileno Ubuntu fornece fontes explicitamente~/.bashrc. Além de impedir a execução não intencional em shells remotos não interativos, colocar suas adições~/.bashrcabaixo da verificação de interatividade também impede que ela seja executada involuntariamente no caso estranho de um shell de logon não interativo.

3 O padrão do Ubuntu.bashrcverifica se~/.bash_aliasesexiste ([ -f ~/.bash_aliases ]) e o origina (. ~/.bash_aliases) se existir. O código que você postou verifica que o.bashrcarquivomodificadoexecuta essas ações - parece que a única alteração foi o código que você adicionou na parte superior.

Eliah Kagan
fonte
Essa resposta cobriu todas as perguntas que eu tinha, grande (talvez mencionar que .bash_aliases é esperado para ser provenientes de .bashrc
Eckes
@EliahKagan, na verdade, eu não notei essa frase no meio, gritos. A ênfase que esta resposta coloca na localização dos aliases fez com que fosse lida como se fosse um problema maior do que realmente é. Como seria se , por exemplo, os pseudônimos também fossem aplicados em invólucros não interativos ... Entendo seu ponto de manter a condição de guarda primeiro, mas parecemos discordar da ordem em que essas questões diferentes devem ser priorizadas. ;)
ilkkachu 5/09/19
@ilkkachu Sim, é possível que discordemos disso. Por outro lado, comecei a escrever esta resposta depois que o mook765 já havia sido publicado e o OP já a havia marcado como aceita. Por isso, decidi iniciar essa resposta consultando a resposta (" mook765 está totalmente correto sobre a causa do problema e a solução proposta nessa resposta corrige o erro de sintaxe") antes de fazer o resto da minha resposta sobre o solução alternativa de colocá-los em outro lugar que não seja o topo do arquivo.
Eliah Kagan 5/09/19
2
@eckes Obrigado pelo conselho - adicionei algumas notas de fim para cobrir essa e algumas questões relacionadas, para os leitores que estão interessados. (A razão pela qual não considero o ~/.bashrcfornecimento ~/.bash_aliasesum ponto especialmente importante nesse contexto é que a inspeção do ~/.bashrcarquivo do OP revela que o código que o fez permaneceu intacto. É, no entanto, relevante e interessante, e você direito de sugerir que ser mencionado).
Elias Kagan