„Błąd składni w pobliżu nieoczekiwanego tokena” po edycji .bashrc

11

Próbuję uzyskać dostęp do schowka, ale gdy wprowadzam dane source ~/.bashrc w terminalu, pojawia się ten błąd:

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

Próbowałem wykonać samouczek z odpowiedzi Gary'ego Woodfine'a na dostęp do schowka z wiersza poleceń .

Dane wyjściowe cat ~/.bashrcto:

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

To jest na Ubuntu 19.04. Czy ktoś może mi pomóc dowiedzieć się, jak to naprawić?

taran
źródło

Odpowiedzi:

16

Zastrzeżenie znajduje się w drugiej linii:

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

To powinno być:

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

Wygląda na to, że zapomniałeś trafić Enterpo wprowadzeniu drugiego aliasu, co spowodowało # ~/.bash...bezpośrednie podążanie za twoją aliasdefinicją w tym samym wierszu. Bez poprzedniej spacji # ~/.bash...powłoka nie mogłaby być interpretowana jako komentarz, ale jako część argumentu aliaspolecenia.

Polecam również umieszczenie aliasów w pliku, ~/.bash_aliasesktóry będzie pozyskiwany po uruchomieniu ~/.bashrc, więc nie trzeba go edytować ~/.bashrci ostatecznie zepsuć.

Jeśli nalegasz na umieszczenie aliasów ~/.bashrc, dodaj je na końcu pliku.

Aby uzyskać głębszy wgląd w ten temat, zapoznaj się z doskonałą odpowiedzią Eliasza na twoje pytanie.

mook765
źródło
6
Ta odpowiedź byłaby o wiele lepsza, gdybyś wyjaśnił, dlaczego ta poprawka działa
Andy
Dzięki! Przy okazji, nawet jeśli ktoś zdecyduje się nie stosować się do mojej rady umieszczania aliasów gdzieś po sprawdzeniu interaktywności, polecam # ~/.bashrc: executed by bash(1) for non-login shells.zachować pierwszą linię. Nie ma technicznych powodów, aby zmuszać go do pojawienia się jako pierwszy (lub wcale). Ale to komentarz dokumentujący cały plik. Jest to dość mylące dla ludzkich czytelników, ponieważ pojawia się po innym kodzie. Rozumiem, jeśli nie chcesz tego zmienić, zwłaszcza że PO zaakceptował tę odpowiedź taką, jaka była. (Myślę, że edytowanie tego lub po prostu pozostawienie go jest uzasadnione w danych okolicznościach).
Eliah Kagan,
„preseed” - miałeś na myśli „poprzedzać”?
Michael Harvey,
20

mook765 ma całkowitą rację co do przyczyny problemu, a rozwiązanie zaproponowane w tej odpowiedzi naprawia błąd składniowy, ale zalecam rozwiązanie go w inny sposób.

Można umieszczać definicje aliasów .bashrc, ale najlepiej nie umieszczać ich - ani nic takiego - na samej górze tego pliku.

Wydaje nam się, .bashrcże pochodzą one wyłącznie z interaktywnych powłok, ale tak nie jest. Nieinteraktywne zdalne powłoki ( jeśli bash identyfikuje je jako takie ) również źródłowe .bashrc. Dlatego domyślna .bashrc1 Ubuntu zawiera ten kod: 2

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

Zasadniczo wszystko, co umieścisz, w .bashrctym między innymi definicje aliasów, powinno pójść gdzieś poniżej tego. Powinieneś zawsze umieszczać własny kod powyżej tego kodu, tylko jeśli masz wyraźny powód, aby to zrobić, co jest rzadkie.

Możesz umieścić definicje aliasów w dowolnym miejscu poniżej tego kodu , choć sugeruję umieszczenie ich na samym końcu pliku. Lub wolisz umieścić je w pobliżu niektórych definicji aliasów w pliku. Lub wolisz umieścić je w osobnym pliku ~/.bash_aliases, który możesz utworzyć, jeśli nie istnieje. 3 Każda z tych opcji jest w porządku.

Oto jeden z najczęstszych przykładów dziwnych i nieoczekiwanych efektów, które stawiają własny kod powyżej kontroli interaktywności. Ten szczególny problem występuje, gdy kod generuje dane wyjściowe, co nie powinno się zdarzyć z definicji aliasu. (Używany alias może oczywiście rozwinąć się w polecenie, które generuje dane wyjściowe, ale poprawna pod względem składni definicja aliasu nie powinna generować danych wyjściowych, chyba że -pzostanie przekazana opcja alias.) Nie spodziewam się, że definicje aliasów zwykle powodują problemy, nawet jeśli działaj w nieinteraktywnych powłokach. Nieinteraktywne powłoki i tak nie domyślnie rozszerzają alias (chociaż jest to tylko domyślna). Jeśli jednak ostatecznie spowodują nieoczekiwane efekty, prawdopodobnie nikt nie pomyśli o tym.

Jest to wprawdzie tylko słaby powód, aby unikać umieszczania definicji aliasów powyżej kontroli interaktywności .bashrc. Jednak, ponieważ nie ma absolutnie żadnych korzyści robić to w porównaniu do wprowadzenia ich nigdzie indziej w pliku, polecam następujące ogólne podejście tylko wprowadzenie kodu powyżej tej kontroli, które celowo zamierza uruchomić w nieinterakcyjnych odległych muszli.


Innym interesującym aspektem tego jest to, że był to błąd składniowy:

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

#uruchamia komentarze, które mogą wykonywać polecenia. Jednak #znak nie powoduje rozpoczęcia komentarza, gdy pojawia się w większym słowie, z wyjątkiem pierwszego znaku tego słowa. (W tym sensie „słowo” obejmuje rzeczy takie jak pbpaste='xclip -selection clipboard -o'#, ze względu na cytowanie ). Poniższy tekst, który miał być komentarzem, jest traktowany jako dodatkowy argument do aliaswbudowanego. Występuje jednak błąd podczas ich analizowania z powodu nieoczekiwanej obecności (, która ma specjalne znaczenie dla powłoki, ale która nie ma sensu w tym kontekście. W efekcie aliaswbudowane narzędzie nigdy się nie uruchamia, a zamiast tego pojawia się błąd składniowy.

Dlatego rzeczywiście można naprawić błąd składniowy za pomocą edycji jednoznakowej , umieszczając spację między znakami 'i #w tym wierszu. Ale jak szczegółowo opisano powyżej, polecam pójść dalej i przenieść definicje aliasów znacznie niżej w pliku.


1 Domyślne.bashrcw Ubuntu można wyświetlić pod/etc/skel/.bashrcwarunkiem, że plik nie został zmodyfikowany. Jest on kopiowany do katalogu domowego użytkownika podczas jego tworzenia. Podobnie jak wiele plików w Ubuntu, ten plik jest minimalnie zmieniany z Debiana, dystrybucji, z której pochodzi Ubuntu. Porady zawarte w tym poście dotyczą zarówno Bash w Debianie, jak i Ubuntu, ale niekoniecznie mają zastosowanie bez modyfikacji Bash we wszystkich systemach GNU / Linux.

2 Możliwe jest również , choć rzadkie, uruchamianie siębashjako nieinteraktywna powłoka logowania. Podobnie jak interaktywne powłoki logowania, taka powłoka~/.profileautomatycznieźródła, a domyślne~./profilew Ubuntu jawnie źródeł~/.bashrc. Oprócz zapobiegania niezamierzonemu wykonaniu w nieinteraktywnych zdalnych powłokach, umieszczenie swoich dodatków~/.bashrcponiżej kontroli interaktywności zapobiega również ich niezamierzonemu wykonaniu w dziwnym przypadku nieinteraktywnej powłoki logowania.

3 Domyślna wersja Ubuntu.bashrcsprawdza, czy~/.bash_aliasesistnieje ([ -f ~/.bash_aliases ]), a. ~/.bash_aliasesjeśli to robi,pobiera ją (). Opublikowany kod weryfikuje, czy zmodyfikowany.bashrcplik wykonuje te działania - wygląda na to, że jedyną zmianą był kod dodany u góry.

Eliah Kagan
źródło
Ta odpowiedź obejmowała wszystkie moje pytania, świetnie (może powinienem wspomnieć, że .bash_aliases ma pochodzić z .bashrc
eckes
@EliahKagan, właściwie nie zauważyłem tego zdania w środku, ups. Nacisk, jaki ta odpowiedź kładzie na lokalizację aliasów, sprawił, że przeczytano ją tak, jakby była większym problemem niż w rzeczywistości. Jak by to było, gdyby np. Aliasy były również stosowane w nieinteraktywnych powłokach ... Rozumiem twój punkt widzenia dotyczący utrzymania stanu ochrony na pierwszym miejscu, ale wydaje nam się, że nie zgadzamy się co do kolejności, w jakiej należy traktować priorytetowo te różne problemy. ;)
ilkkachu
@ilkkachu Tak, możliwe, że się z tym nie zgadzamy. Z drugiej strony zacząłem pisać tę odpowiedź po tym, jak mook765 już został opublikowany, a OP oznaczył ją jako zaakceptowaną. Postanowiłem więc rozpocząć tę odpowiedź, odwołując się do tej odpowiedzi („ mook765 ma całkowitą rację co do przyczyny problemu, a rozwiązanie zaproponowane w tej odpowiedzi naprawia błąd składniowy”), a następnie wykorzystuję większość mojej odpowiedzi na temat alternatywne rozwiązanie umieszczenia ich gdzieś indziej niż na samej górze pliku.
Eliah Kagan,
2
@eckes Dzięki za radę - dodałem kilka przypisów końcowych, aby omówić to i niektóre powiązane kwestie, dla tych czytelników, którzy są zainteresowani. (Powodem, dla którego nie uważam ~/.bashrcpozyskiwania ~/.bash_aliasesza szczególnie ważny punkt w tym kontekście, jest to, że kontrola ~/.bashrcpliku OP ujawnia, że ​​kod, który to robi, pozostał nietknięty. Jest to jednak zarówno istotne, jak i interesujące, a ty prawo do zasugerowania, aby o tym wspomnieć.)
Eliah Kagan,