«Синтаксическая ошибка рядом с неожиданным токеном» после редактирования .bashrc

11

Я пытаюсь получить доступ к буферу обмена, но когда я ввожу source ~/.bashrc в терминал, я получаю эту ошибку:

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

Я пытался сделать учебник в ответе Гари Woodfine в к командной строке Буфер обмена доступу .

Вывод 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

Это на Ubuntu 19.04. Может кто-нибудь помочь мне разобраться, как это исправить?

таран
источник

Ответы:

16

Предостережение во второй строке:

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

Которые должны быть:

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

Похоже, вы забыли нажать Enterпосле ввода второго псевдонима, в результате чего # ~/.bash...сразу же после вашего aliasопределения в той же строке. Без предшествующего пробела # ~/.bash...нельзя интерпретировать оболочку как комментарий, а как часть аргумента aliasкоманды.

Я бы также порекомендовал поместить псевдонимы в файл, ~/.bash_aliasesкоторый будет получен при ~/.bashrcвыполнении, так что вам не нужно редактировать ~/.bashrcи, в конце концов, испортить его.

Если вы настаиваете на размещении псевдонимов ~/.bashrc, добавьте их в конец файла.

Чтобы глубже понять эту тему, обратитесь к прекрасному ответу Элии на ваш вопрос.

mook765
источник
6
Этот ответ был бы намного лучше, если бы вы объяснили, почему исправление работает
Энди
Благодарность! Кстати, даже если кто-то решит не следовать моему совету о размещении псевдонимов где-нибудь после проверки интерактивности, я рекомендую # ~/.bashrc: executed by bash(1) for non-login shells.оставить в качестве первой строки. Нет никаких технических причин, заставляющих его появляться первым (или вообще). Но это комментарий, документирующий весь файл. Так что это довольно запутанно для читателей, чтобы они появлялись после другого кода. Я понимаю, что если вы не хотите это менять, тем более что ОП принял этот ответ таким, каким он был. (Я думаю, что редактирование для этого или просто выход из него разумны в данных обстоятельствах.)
Элия ​​Каган
«preseed» - вы имели в виду «предшествовать»?
Майкл Харви
20

mook765 совершенно правильно определил причину проблемы, и решение, предложенное в этом ответе, исправляет синтаксическую ошибку, но я рекомендую вам решить ее по-другому.

Хорошо добавлять определения псевдонимов .bashrc, но лучше не помещать их - или что-нибудь - в самый верх этого файла.

Мы склонны думать, .bashrcчто источником являются только интерактивные оболочки, но на самом деле это не так. Неинтерактивные удаленные оболочки ( если bash определяет их как таковые ) также являются источником .bashrc. Вот почему в Ubuntu по умолчанию .bashrc1 содержится следующий код: 2

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

В основном все, что вы вводите .bashrc, включая определения псевдонимов, но не ограничиваясь ими, должно быть где-то ниже этого. Вы должны когда-либо ставить свой собственный код над этим кодом, только если у вас есть для этого явная причина, что встречается редко.

Вы можете поместить свои определения псевдонимов в любом месте ниже этого кода , хотя я предлагаю разместить их в самом конце файла. Или вы можете предпочесть поместить их рядом с некоторыми из существующих определений псевдонимов в файле. Или вы можете предпочесть поместить их в отдельный файл ~/.bash_aliases, который вы можете создать, если он не существует. 3 Любой из этих вариантов в порядке.

Вот один из наиболее распространенных примеров странных и неожиданных эффектов, когда ваш собственный код выше проверки интерактивности. Эта конкретная проблема возникает, когда код производит вывод, что не должно происходить из определения псевдонима. (Псевдоним, когда он используется, может, конечно, расширяться до команды, которая производит вывод, но синтаксически правильное определение псевдонима не должно производить вывод, если -pпараметр не передан alias.) Я не ожидаю, что определения псевдонима обычно вызывают проблемы, даже если они бегать в неинтерактивных оболочках. Неинтерактивные оболочки не выполняют расширение псевдонимов по умолчанию (хотя это просто значение по умолчанию). Однако, если они в конечном итоге приводят к неожиданным эффектам, то, вероятно, никто не подумает проверить это.

Это, по общему признанию, лишь слабая причина, чтобы не ставить определения псевдонимов выше проверки интерактивности .bashrc. Однако, поскольку это абсолютно бесполезно по сравнению с размещением их где-либо еще в файле, я рекомендую следовать общему подходу, заключающемуся только в том, чтобы поместить код выше той проверки, что вы намеренно собираетесь работать в неинтерактивных удаленных оболочках.


Другой интересный аспект этого - то, почему это была синтаксическая ошибка:

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

#запускает комментарии, которым разрешено следовать командам. Однако #символ не имеет эффекта начала комментария, когда он появляется в большем слове, кроме как в качестве первого символа этого слова. (В этом смысле «слово» включает в себя вещи , как pbpaste='xclip -selection clipboard -o'#, из - за приведение .) Следующий текст, который был задуман как комментарий, принимаются в качестве дополнительных аргументов aliasвстроенной команды. Но при их синтаксическом анализе возникает ошибка из-за неожиданного присутствия (, которое имеет особое значение для оболочки, но не имеет смысла в этом контексте. В результате aliasвстроенная функция фактически никогда не запускается, и вместо этого вы получаете синтаксическую ошибку.

Таким образом, было бы на самом деле можно исправить ошибку синтаксиса с одного символа редактирования , поставив пробел между 'и #символов на этой строке. Но, как подробно описано выше, я рекомендую пойти дальше и переместить определения псевдонимов в файл намного ниже.


1 По умолчанию.bashrcв Ubuntu можно посмотреть по адресу/etc/skel/.bashrc, если вы не изменили этот файл. Это копируется в домашний каталог пользователя при его создании. Как и многие файлы в Ubuntu, этот файл минимально отличается от Debian, дистрибутива, из которого происходит Ubuntu. Рекомендации в этом посте применимы как к Bash в Debian, так и к Ubuntu, но не обязательно применяются без изменений к Bash во всех системах GNU / Linux.

2 Также возможно , хотя и редко, запускатьсяbashкак неинтерактивная оболочка входа в систему. Подобно интерактивным оболочкам входа в систему, такая оболочка получает источники~/.profileавтоматически, а по умолчанию~./profileв Ubuntu - источники явные~/.bashrc. Помимо предотвращения непреднамеренного выполнения в неинтерактивных удаленных оболочках, добавление ваших дополнений~/.bashrcниже проверки интерактивности также предотвращает его непреднамеренное выполнение в странном случае неинтерактивной оболочки входа в систему.

3 Ubuntu по умолчанию.bashrcпроверяет,~/.bash_aliasesсуществуетли([ -f ~/.bash_aliases ]), и отправляет его (. ~/.bash_aliases), если это так. Размещенный вами код подтверждает, что ваш измененный.bashrcфайл выполняет эти действия - похоже, единственным изменением к нему был код, который вы добавили вверху.

Элия ​​Каган
источник
Этот ответ охватил все вопросы, которые у меня были, отлично (возможно, стоит упомянуть, что .bash_aliases, как ожидается, будет получен из .bashrc
eckes
@EliahKagan, вообще-то, я не заметил это предложение посередине, к сожалению. Акцент в этом ответе делается на расположении псевдонимов, которые читаются так, как если бы это было более серьезной проблемой, чем на самом деле. Как и в случае , если , например, псевдонимы были применены и в неинтерактивных оболочках ... Я вижу, что вы сначала сохраняете условие охраны, но мы, похоже, не согласны с порядком, в котором эти различные проблемы должны быть приоритетными. ;)
ilkkachu
@ilkkachu Да, возможно, мы не согласны с этим. С другой стороны, я начал писать этот ответ после того, как mook765 уже были опубликованы, и ОП уже пометил его как принятый. Поэтому я решил начать этот ответ со ссылки на этот ответ (« mook765 совершенно корректен в отношении причины проблемы, а решение, предлагаемое в этом ответе, исправляет синтаксическую ошибку»), прежде чем сделать большую часть оставшейся части моего ответа о альтернативное решение положить их где-то еще, чем в самом верху файла.
Элия ​​Каган
2
@eckes Спасибо за совет - я добавил несколько сносок, чтобы охватить это и некоторые связанные вопросы, для тех читателей, которые заинтересованы. (Причина, по которой я не считаю, что ~/.bashrcпоиск источников данных ~/.bash_aliasesявляется особенно важным моментом в этом контексте, заключается в том, что проверка ~/.bashrcфайла OP выявляет, что код, который делает это, остался неповрежденным. Однако он уместен и интересен, и вы Правильно предложить, чтобы это было упомянуто.)
Элия ​​Каган