"Error de sintaxis cerca de token inesperado" después de editar .bashrc

11

Estoy tratando de acceder al portapapeles pero cuando ingreso source ~/.bashrc en el terminal me sale este error:

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

Traté de hacer el tutorial en la respuesta de Gary Woodfine a Command Line Clipboard Access .

La salida de cat ~/.bashrces:

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

Esto está en Ubuntu 19.04. ¿Alguien puede ayudarme a descubrir cómo solucionar esto?

taran
fuente

Respuestas:

16

La advertencia está en la segunda línea:

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

Eso debería ser:

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

Parece que olvidó presionar Enterdespués de ingresar el segundo alias que resultó en # ~/.bash...seguir directamente su aliasdefinición en la misma línea. Sin un espacio anterior # ~/.bash...no se podría interpretar como un comentario por parte del shell, sino como parte del argumento del aliascomando.

También recomendaría colocar alias en el archivo ~/.bash_aliasesque se originará cuando ~/.bashrcse ejecute, para que no necesite editar ~/.bashrcy eventualmente estropearlo.

Si insiste en colocar alias ~/.bashrc, agréguelos al final del archivo.

Para una visión más profunda de este tema, consulte la excelente respuesta de Eliah a su pregunta.

mook765
fuente
66
Esta respuesta sería mucho mejor si explicaras por qué funciona la solución
Andy
¡Gracias! Por cierto, incluso si uno elige no seguir mi consejo de colocar los alias en algún lugar después de la verificación de interactividad, recomiendo que # ~/.bashrc: executed by bash(1) for non-login shells.se mantenga como primera línea. No hay ninguna razón técnica que lo obligue a aparecer primero (o en absoluto). Pero es un comentario que documenta todo el archivo. Por lo tanto, es bastante confuso para los lectores humanos que aparezca después de otro código. Entiendo que si no quieres cambiar eso, especialmente porque el OP aceptó esta respuesta tal como era. (Creo que editar para eso o simplemente dejarlo son razonables dadas las circunstancias).
Eliah Kagan
'preseed': ¿quiso decir 'preceder'?
Michael Harvey
20

mook765 es completamente correcto acerca de la causa del problema, y ​​la solución propuesta en esa respuesta corrige el error de sintaxis, pero le recomiendo que lo resuelva de una manera diferente.

Está bien poner definiciones de alias .bashrc, pero es mejor no ponerlas, ni nada, en la parte superior de ese archivo.

Tendemos a pensar .bashrcque solo provienen de shells interactivos, pero este no es el caso. Los shells remotos no interactivos ( si bash los identifica como tales ) también son fuente .bashrc. Es por eso que el valor predeterminado .bashrc1 de Ubuntu contiene este código: 2

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

Básicamente, todo lo que .bashrcingrese, incluidas, entre otras, las definiciones de alias, debería ir a algún lugar debajo de eso. Solo debe poner su propio código encima de ese código si tiene una razón clara para hacerlo, lo cual es raro.

Puede colocar sus definiciones de alias en cualquier lugar debajo de ese código , aunque sugiero colocarlas al final del archivo. O tal vez prefiera colocarlos cerca de algunas de las definiciones de alias existentes en el archivo. O tal vez prefiera colocarlos en un archivo separado ~/.bash_aliases, que puede crear si no existe. 3 Cualquiera de estas opciones está bien.

Este es uno de los ejemplos más comunes de los efectos extraños e inesperados que puede tener el propio código por encima de la verificación de interactividad. Ese problema particular ocurre cuando el código produce una salida, lo que no debería ocurrir a partir de una definición de alias. (El alias, cuando se usa, por supuesto puede expandirse a un comando que produce salida, pero una definición de alias sintácticamente correcta no debería producir salida a menos que -pse pase la opción alias). No espero que las definiciones de alias usualmente causen problemas incluso si ejecutarse en shells no interactivos. Los shells no interactivos no realizan expansión de alias de forma predeterminada de todos modos (aunque esto es simplemente un valor predeterminado). Sin embargo, si terminan produciendo efectos inesperados, es probable que nadie piense en verificar eso.

Esto es sin duda una razón débil para evitar poner definiciones de alias por encima de la verificación de interactividad .bashrc. Sin embargo, dado que no hay absolutamente ningún beneficio de hacerlo frente a ponerlos en otro sitio en el archivo, recomiendo seguir el enfoque general de solamente poner el código de registro de entrada que forma deliberada intención de correr en los depósitos remotos no interactivas.


El otro aspecto interesante de esto es por qué esto fue un error de sintaxis:

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

#inicia comentarios, que pueden seguir comandos. Sin embargo, el #carácter no tiene el efecto de comenzar un comentario cuando aparece en una palabra más grande, excepto como el primer carácter de esa palabra. (En este sentido, "palabra" incluye cosas como pbpaste='xclip -selection clipboard -o'#, debido a las citas ). El siguiente texto, que fue pensado como un comentario, se toma como argumentos adicionales para el texto aliasincorporado. Pero se produce un error al analizarlos, debido a la presencia inesperada de (, que tiene un significado especial para el shell, pero que no tiene sentido en ese contexto. El efecto es que la aliasversión incorporada en realidad nunca se ejecuta, y en su lugar obtiene un error de sintaxis.

Por lo tanto, en realidad sería posible corregir el error de sintaxis con una edición de un carácter , colocando un espacio entre los caracteres 'y #en esa línea. Pero como se detalla anteriormente, recomiendo ir más allá y mover las definiciones de alias mucho más abajo en el archivo.


1 El valor predeterminado.bashrcen Ubuntu se puede ver en/etc/skel/.bashrc, siempre que no haya modificado ese archivo. Esto se copia en el directorio de inicio de un usuario cuando se crea el usuario. Al igual que muchos archivos en Ubuntu, este archivo se modifica mínimamente de Debian, la distribución de la que se deriva Ubuntu. El consejo en esta publicación se aplica tanto a Bash en Debian como a Ubuntu, pero no necesariamente se aplica sin modificación a Bash en todos los sistemas GNU / Linux.

2 También es posible , aunque raro, comenzarbashcomo un shell de inicio de sesión no interactivo. Al igual que los shells de inicio de sesión interactivos, dicho shell se origina~/.profileautomáticamente y el valor predeterminado~./profileen Ubuntu explícitamente lo hace~/.bashrc. Además de evitar la ejecución involuntaria en shells remotos no interactivos, poner sus adiciones~/.bashrcdebajo de la verificación de interactividad también evita que se ejecute involuntariamente en el extraño caso de un shell de inicio de sesión no interactivo.

3 Las.bashrccomprobacionespredeterminadas de Ubuntusi~/.bash_aliasesexisten ([ -f ~/.bash_aliases ]) y las obtienen (. ~/.bash_aliases) si es así. El código que publicó verifica que su.bashrcarchivomodificadorealiza esas acciones; parece que el único cambio fue el código que agregó en la parte superior.

Eliah Kagan
fuente
Esa respuesta cubrió todas las preguntas que tenía, genial (tal vez debería mencionar que se espera que .bash_aliases provenga de .bashrc
eckes el
@EliahKagan, en realidad, no noté esa frase en el medio, ¡vaya! El énfasis que esta respuesta pone en la ubicación de los alias lo hizo leer como si fuera un problema mayor de lo que realmente es. Como sería si , por ejemplo, los alias se aplicaran también en caparazones no interactivos ... Veo su punto sobre mantener la condición de guardia primero, pero parece que no estamos de acuerdo en el orden en que estos diferentes temas deben priorizarse. ;)
ilkkachu 05 de
@ilkkachu Sí, es posible que no estemos de acuerdo con eso. Por otro lado, comencé a escribir esta respuesta después de que el mook765 ya estaba publicado y el OP ya lo había marcado como aceptado. Así que decidí comenzar esta respuesta refiriéndome a esa respuesta (" mook765 es completamente correcto sobre la causa del problema, y ​​la solución propuesta en esa respuesta corrige el error de sintaxis") antes de hacer la mayor parte del resto de mi respuesta sobre el solución alternativa de colocarlos en otro lugar que no sea la parte superior del archivo.
Eliah Kagan
2
@eckes Gracias por el consejo: he agregado algunas notas finales para cubrir eso y algunos temas relacionados, para aquellos lectores que estén interesados. (La razón por la que no considero que el ~/.bashrcabastecimiento ~/.bash_aliasessea ​​un punto especialmente importante en este contexto es que la inspección del ~/.bashrcarchivo del OP revela que el código que lo ha hecho permanece intacto. Sin embargo, es relevante e interesante, y usted es derecho a sugerir que se mencione.)
Eliah Kagan