«Erreur de syntaxe près d'un jeton inattendu» après la modification de .bashrc

11

J'essaie d'accéder au presse-papiers mais lorsque j'entre source ~/.bashrc dans le terminal, j'obtiens cette erreur:

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

J'ai essayé de faire le tutoriel dans la réponse de Gary Woodfine à l' accès au presse-papiers en ligne de commande .

La sortie de cat ~/.bashrcest:

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

C'est sur Ubuntu 19.04. Quelqu'un peut-il m'aider à comprendre comment résoudre ce problème?

taran
la source

Réponses:

16

La mise en garde est dans la deuxième ligne:

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

Ça devrait être:

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

Il semble que vous ayez oublié de frapper Enteraprès avoir entré le deuxième alias, ce qui a entraîné le # ~/.bash...suivi direct de votre aliasdéfinition sur la même ligne. Sans un espace précédent, # ~/.bash...il ne pouvait pas être interprété comme un commentaire par le shell mais comme une partie de l'argument de la aliascommande.

Je recommanderais également de placer des alias dans le fichier ~/.bash_aliasesqui sera généré lors de ~/.bashrcson exécution, de sorte que vous n'avez pas besoin de le modifier ~/.bashrcet éventuellement de le gâcher.

Si vous insistez pour placer des alias ~/.bashrc, ajoutez-les à la fin du fichier.

Pour un aperçu plus approfondi de ce sujet, veuillez vous référer à l'excellente réponse d' Elie à votre question.

mook765
la source
6
Cette réponse serait bien meilleure si vous expliquiez pourquoi le correctif fonctionne
Andy
Merci! Btw même si l'on choisit de ne pas suivre mon conseil de mettre les alias quelque part après le contrôle d'interactivité, je recommande de # ~/.bashrc: executed by bash(1) for non-login shells.rester en première ligne. Aucune raison technique ne l'oblige à apparaître en premier (ou pas du tout). Mais c'est un commentaire documentant l'ensemble du dossier. Il est donc assez déroutant pour les lecteurs humains qu'il apparaisse après un autre code. Je comprends que vous ne vouliez pas changer cela, d'autant plus que le PO a accepté cette réponse telle qu'elle était. (Je pense que le montage pour cela ou simplement le laisser est à la fois raisonnable dans les circonstances.)
Eliah Kagan
«prédéfini» - vouliez-vous dire «précéder»?
Michael Harvey
20

mook765 est tout à fait correct quant à la cause du problème, et la solution proposée dans cette réponse corrige l'erreur de syntaxe, mais je vous recommande de le résoudre d'une manière différente.

C'est bien de mettre des définitions d'alias .bashrc, mais il est préférable de ne pas les mettre - ou quoi que ce soit - tout en haut de ce fichier.

Nous avons tendance à penser .bashrcque ces sources proviennent uniquement de shells interactifs, mais ce n'est en fait pas le cas. Les shells distants non interactifs ( si bash les identifie comme tels ) sont également source .bashrc. C'est pourquoi Ubuntu par défaut .bashrc1 contient ce code: 2

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

Fondamentalement, tout ce que vous mettez .bashrc, y compris, mais sans s'y limiter, les définitions d'alias, devrait aller quelque part en dessous. Vous ne devriez jamais mettre votre propre code au-dessus de ce code que si vous avez une raison claire de le faire, ce qui est rare.

Vous pouvez placer vos définitions d'alias n'importe où en dessous de ce code , bien que je suggère de les mettre à la toute fin du fichier. Vous pouvez également préférer les placer près de certaines définitions d'alias existantes dans le fichier. Vous pouvez également préférer les placer dans un fichier séparé ~/.bash_aliases, que vous pouvez créer s'il n'existe pas. 3 Chacun de ces choix est très bien.

Voici l'un des exemples les plus courants des effets bizarres et inattendus de mettre son propre code au - dessus du contrôle d'interactivité. Ce problème particulier se produit lorsque le code produit une sortie, ce qui ne devrait pas se produire à partir d'une définition d'alias. (L'alias, lorsqu'il est utilisé, peut bien sûr s'étendre à une commande qui produit une sortie, mais une définition d'alias syntaxiquement correcte ne devrait pas produire de sortie à moins que l' -poption ne soit passée à alias.) Je ne m'attends pas à ce que les définitions d'alias causent généralement des problèmes même si elles exécuter dans des shells non interactifs. Les shells non interactifs n'effectuent pas l'expansion d'alias par défaut de toute façon (bien que ce soit simplement un défaut). Cependant, s'ils finissent par produire des effets inattendus, il est probable que personne ne pensera à vérifier cela.

Ce n'est certes qu'une faible raison pour éviter de placer des définitions d'alias au-dessus du contrôle d'interactivité .bashrc. Cependant, étant donné qu'il n'y a absolument aucun avantage à le faire par rapport à les placer n'importe où ailleurs dans le fichier, je recommande de suivre l'approche générale de ne mettre que du code au-dessus de cette vérification que vous avez délibérément l' intention d'exécuter dans des shells distants non interactifs.


L'autre aspect intéressant de cela est la raison pour laquelle il s'agissait d'une erreur de syntaxe:

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

#démarre les commentaires, qui sont autorisés à suivre les commandes. Toutefois, le #caractère n'a pas pour effet de commencer un commentaire lorsqu'il apparaît dans un mot plus gros, sauf en tant que premier caractère de ce mot. (Dans ce sens, "mot" inclut des choses comme pbpaste='xclip -selection clipboard -o'#, en raison de la citation .) Le texte suivant, qui était destiné à être un commentaire, est considéré comme des arguments supplémentaires à la fonction aliasintégrée. Mais une erreur se produit lors de leur analyse, en raison de la présence inattendue de (, qui a une signification particulière pour le shell, mais qui n'a pas de sens dans ce contexte. L'effet est que la fonction aliasintégrée ne s'exécute jamais et vous obtenez une erreur de syntaxe à la place.

Par conséquent, il serait en fait possible de corriger l'erreur de syntaxe avec une modification à un caractère , en mettant un espace entre les caractères 'et #sur cette ligne. Mais comme détaillé ci-dessus, je recommande d'aller plus loin et de déplacer les définitions d'alias beaucoup plus bas dans le fichier.


1 La valeur.bashrcpardéfautdans Ubuntu peut être consultée à/etc/skel/.bashrc, tant que vous n'avez pas modifié ce fichier. Il est copié dans le répertoire personnel d'un utilisateur lors de sa création. Comme de nombreux fichiers dans Ubuntu, ce fichier est légèrement modifié de Debian, la distribution dont Ubuntu est dérivé. Les conseils de ce post s'appliquent à Bash dans Debian ainsi qu'à Ubuntu, mais ils ne s'appliquent pas nécessairement sans modification à Bash dans tous les systèmes GNU / Linux.

2 Il est également possible , bien que rare, de démarrer enbashtant que shell de connexion non interactif. Comme les shells de connexion interactifs, un tel shell sources~/.profileautomatiquement, et la valeur~./profilepardéfautdans Ubuntu sources explicitement~/.bashrc. En plus d'empêcher l'exécution involontaire dans des shells distants non interactifs, le fait de placer vos ajouts en~/.bashrcdessous du contrôle d'interactivité l'empêche également d'être exécuté involontairement dans le cas étrange d'un shell de connexion non interactif.

3 Par défaut, Ubuntu.bashrcvérifie s'il~/.bash_aliasesexiste ([ -f ~/.bash_aliases ]) et le source (. ~/.bash_aliases) si tel est le cas. Le code que vous avez publié vérifie que votre.bashrcfichiermodifiéeffectue ces actions - il semble que la seule modification apportée soit le code que vous avez ajouté en haut.

Eliah Kagan
la source
Cette réponse a couvert toutes les questions que j'avais, très bien (je devrais peut-être mentionner que .bash_aliases devrait provenir de .bashrc
eckes
@EliahKagan, en fait, je n'ai pas remarqué cette phrase au milieu, oups. L'accent mis par cette réponse sur l'emplacement des alias l'a fait croire que ce serait un problème plus important qu'il ne l'est réellement. Comme ce serait le cas si , par exemple, les alias étaient également appliqués dans des shells non interactifs ... Je vois votre point sur le maintien de la condition de garde en premier, mais nous semblons ne pas être d'accord sur l'ordre dans lequel ces différents problèmes devraient être priorisés. ;)
ilkkachu
@ilkkachu Oui, il est possible que nous ne soyons pas d'accord à ce sujet. D'un autre côté, j'ai commencé à écrire cette réponse après que le mook765 ait déjà été publié et que l'OP l'avait déjà marqué comme accepté. J'ai donc décidé de commencer cette réponse en me référant à cette réponse (" mook765 est tout à fait correct quant à la cause du problème, et la solution proposée dans cette réponse corrige l'erreur de syntaxe") avant de tirer ensuite l'essentiel du reste de ma réponse sur le solution alternative de les placer ailleurs que tout en haut du fichier.
Eliah Kagan
2
@eckes Merci pour les conseils - J'ai ajouté quelques notes de fin pour couvrir cela et certaines questions connexes, pour les lecteurs intéressés. (La raison pour laquelle je ne considère pas l' ~/.bashrcapprovisionnement ~/.bash_aliasescomme un point particulièrement important dans ce contexte est que l'inspection du ~/.bashrcfichier de l'OP révèle que le code qui le fait est resté intact. Il est cependant à la fois pertinent et intéressant, et vous êtes droit de suggérer qu'il soit mentionné.)
Eliah Kagan