"Помилка синтаксису біля несподіваного маркера" після редагування .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

Я спробував виконати підручник з відповіді Гері Вудфіна на доступ до буфера обміну командного рядка .

Вихід 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, додайте їх у кінці файлу.

Для глибшого ознайомлення з цією темою зверніться до чудової відповіді Іллі на ваше запитання.


6
Ця відповідь була б набагато кращою, якби ви пояснили, чому виправлення працює
Енді

Спасибі! До речі, навіть якщо хтось вирішить не дотримуватися моїх рекомендацій про те, щоб помістити псевдоніми десь після перевірки інтерактивності, я рекомендую # ~/.bashrc: executed by bash(1) for non-login shells.зберігати його як перший рядок. Немає жодних технічних причин змушувати її з’являтися першою (або взагалі). Але це коментар, який документує весь файл. Тож для читачів людини досить заплутано, що він з'явиться після іншого коду. Я розумію, якщо ви не хочете цього змінювати, тим більше, що ОП прийняла цю відповідь такою, якою вона була. (Я думаю, що редагування для цього чи просто залишення його є обґрунтованими за обставин.)
Елія Каган

'заздалегідь' - ви мали на увазі «передувати»?
Майкл Харві

20

mook765 цілком правильно стосується причини проблеми, і рішення, запропоноване в цій відповіді, виправляє синтаксичну помилку, але я рекомендую вам вирішити її по-іншому.

Добре вводити визначення псевдонімів .bashrc, але найкраще не ставити їх - або що-небудь - у верхній частині цього файлу.

Ми схильні вважати .bashrc, що їх отримують лише інтерактивні оболонки, але це насправді не так. Неінтерактивні віддалені оболонки ( якщо Баш ідентифікує їх як таких ) також є джерелом .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файл показує , що код , який робить це залишається незмінним. Це, однак, як актуально і цікаво, і ви право пропонувати згадати.)
Елія Каган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.