"Kesalahan sintaksis dekat token yang tidak terduga" setelah mengedit .bashrc

11

Saya mencoba mengakses clipboard tetapi ketika saya input source ~/.bashrc di terminal saya mendapatkan kesalahan ini:

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

Saya mencoba melakukan tutorial dalam jawaban Gary Woodfine untuk Command Line Clipboard Access .

Output dari cat ~/.bashrcadalah:

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

Ini ada di Ubuntu 19.04. Adakah yang bisa membantu saya mencari cara untuk memperbaikinya?

taran
sumber

Jawaban:

16

Peringatan ada di baris kedua:

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

Itu harus:

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

Sepertinya Anda lupa mengenai hit Entersetelah memasukkan alias kedua yang mengakibatkan # ~/.bash...langsung mengikuti aliasdefinisi Anda di baris yang sama. Tanpa ruang sebelumnya # ~/.bash...tidak dapat diartikan sebagai komentar oleh shell tetapi sebagai bagian dari argumen aliasperintah.

Saya juga merekomendasikan untuk menempatkan alias di file ~/.bash_aliasesyang akan bersumber saat ~/.bashrcdijalankan, sehingga Anda tidak perlu mengedit ~/.bashrcdan akhirnya mengacaukannya.

Jika Anda bersikeras untuk menempatkan alias ~/.bashrc, tambahkan di akhir file.

Untuk wawasan yang lebih mendalam tentang topik ini, silakan merujuk ke jawaban Elia yang luar biasa untuk pertanyaan Anda.

mook765
sumber
6
Jawaban ini akan jauh lebih baik jika Anda menjelaskan mengapa perbaikannya
Andy
Terima kasih! Btw bahkan jika seseorang memilih untuk tidak mengikuti saran saya untuk meletakkan alias di suatu tempat setelah pemeriksaan interaktivitas, saya sarankan # ~/.bashrc: executed by bash(1) for non-login shells.disimpan sebagai baris pertama. Tidak ada alasan teknis untuk memaksanya tampil lebih dulu (atau sama sekali). Tapi ini adalah komentar yang mendokumentasikan seluruh file. Jadi cukup membingungkan bagi pembaca manusia untuk muncul setelah kode lain. Saya mengerti jika Anda tidak ingin mengubahnya, terutama karena OP menerima jawaban ini seperti sebelumnya. (Saya pikir mengedit untuk itu atau meninggalkannya sama-sama masuk akal dalam situasi ini.)
Eliah Kagan
'preseed' - maksud Anda 'mendahului'?
Michael Harvey
20

mook765 sepenuhnya benar tentang penyebab masalah, dan solusi yang diajukan dalam jawaban itu memperbaiki kesalahan sintaks, tetapi saya sarankan Anda menyelesaikannya dengan cara yang berbeda.

Tidak apa-apa untuk memasukkan definisi alias .bashrc, tetapi yang terbaik adalah tidak menempatkannya - atau apa pun - di bagian paling atas file itu.

Kita cenderung menganggap .bashrcsebagai sumber hanya oleh shell interaktif, tetapi ini sebenarnya tidak demikian. Kerang jarak jauh non-interaktif ( jika bash mengidentifikasinya ) juga sumber .bashrc. Itulah sebabnya default Ubuntu .bashrc1 berisi kode ini: 2

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

Pada dasarnya semua yang Anda masukkan .bashrc, termasuk tetapi tidak terbatas pada definisi alias, harus pergi ke suatu tempat di bawah itu. Anda hanya boleh menempatkan kode Anda sendiri di atas kode itu jika Anda memiliki alasan yang jelas untuk melakukannya, yang jarang terjadi.

Anda dapat meletakkan definisi alias Anda di mana saja di bawah kode itu , meskipun saya sarankan meletakkannya di bagian paling akhir file. Atau Anda mungkin lebih suka meletakkannya di dekat beberapa definisi alias yang ada dalam file. Atau Anda mungkin memilih untuk meletakkannya di file terpisah ~/.bash_aliases, yang dapat Anda buat jika tidak ada. 3 Semua pilihan ini baik-baik saja.

Berikut adalah salah satu contoh yang lebih umum dari efek aneh dan tak terduga menempatkan kode sendiri di atas pemeriksaan interaktivitas. Masalah khusus itu terjadi ketika kode menghasilkan output, yang seharusnya tidak terjadi dari definisi alias. (Alias, ketika digunakan, tentu saja dapat meluas ke perintah yang menghasilkan output, tetapi definisi alias yang benar secara sintaksis tidak boleh menghasilkan keluaran kecuali jika -popsi diteruskan alias.) Saya tidak berharap alias definisi biasanya menyebabkan masalah bahkan jika mereka berjalan dalam cangkang non-interaktif. Kerang non-interaktif tidak melakukan ekspansi alias secara default (meskipun ini hanyalah default). Namun, jika mereka akhirnya menghasilkan efek yang tidak terduga, kemungkinan tidak ada yang akan berpikir untuk memeriksanya.

Ini diakui hanya alasan lemah untuk menghindari memasukkan definisi alias di atas interaktivitas .bashrc. Namun, karena sama sekali tidak ada manfaat melakukan hal itu dibandingkan dengan menempatkannya di tempat lain dalam file, saya sarankan mengikuti pendekatan umum dengan hanya menempatkan kode di atas yang memeriksa bahwa Anda sengaja bermaksud untuk menjalankan di shell remote non-interaktif.


Aspek menarik lainnya adalah mengapa ini merupakan kesalahan sintaksis:

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

#memulai komentar, yang diizinkan untuk mengikuti perintah. Namun, #karakter tidak memiliki efek memulai komentar ketika muncul dalam kata yang lebih besar, kecuali sebagai karakter pertama dari kata itu. (Dalam hal ini, "kata" termasuk hal-hal seperti pbpaste='xclip -selection clipboard -o'#, karena mengutip .) Teks berikut, yang dimaksudkan sebagai komentar, diambil sebagai argumen tambahan untuk aliasbuiltin. Tetapi kesalahan terjadi saat mengurai mereka, karena kehadiran yang tak terduga (, yang memiliki arti khusus untuk shell, tetapi yang tidak masuk akal dalam konteks itu. Efeknya adalah bahwa aliasbuiltin sebenarnya tidak pernah berjalan, dan Anda malah mendapatkan kesalahan sintaksis.

Oleh karena itu, sebenarnya mungkin untuk memperbaiki kesalahan sintaks dengan pengeditan satu karakter , dengan menempatkan spasi antara 'dan #karakter pada baris itu. Tetapi seperti yang dijelaskan di atas, saya sarankan untuk melangkah lebih jauh dan memindahkan definisi alias jauh lebih rendah dalam file.


1 Default.bashrcdi Ubuntu dapat dilihat di/etc/skel/.bashrc, selama Anda belum mengubah file itu. Ini disalin ke direktori home pengguna ketika pengguna dibuat. Seperti banyak file di Ubuntu, file ini minimal diubah dari Debian, distribusi dari mana Ubuntu berasal. Saran dalam posting ini berlaku untuk Bash di Debian dan juga Ubuntu, tetapi tidak harus berlaku tanpa modifikasi ke Bash di semua sistem GNU / Linux.

2 Juga mungkin , meskipun jarang, untuk memulaibashsebagai shell login non-interaktif. Seperti shell login interaktif, shell seperti itu sumber~/.profilesecara otomatis, dan default~./profiledi Ubuntu secara eksplisit sumber~/.bashrc. Selain mencegah eksekusi yang tidak disengaja dalam shell jarak jauh non-interaktif, menempatkan tambahan Anda di~/.bashrcbawah pemeriksaan interaktivitas juga mencegahnya dieksekusi secara tidak sengaja dalam kasus aneh dari shell login non-interaktif.

3.bashrc Pemeriksaandefault Ubuntujika~/.bash_aliasesada ([ -f ~/.bash_aliases ]) dan sumbernya (. ~/.bash_aliases) jika ada. Kode yang Anda poskan memverifikasi bahwa.bashrcfileAnda yang dimodifikasimemang melakukan tindakan itu - sepertinya satu-satunya perubahan adalah kode yang Anda tambahkan di bagian atas.

Eliah Kagan
sumber
Jawaban itu mencakup semua pertanyaan yang saya miliki, hebat (mungkin harus menyebutkan bahwa .bash_aliases diharapkan bersumber dari .bashrc
eckes
@ ElliKagan, sebenarnya, saya tidak memperhatikan kalimat itu di tengah, wah. Penekanan jawaban ini menempatkan pada lokasi alias membuatnya membaca seolah-olah itu akan menjadi masalah yang lebih besar dari yang sebenarnya. Seperti jika , misalnya alias diterapkan dalam cangkang noninteraktif juga ... Saya melihat maksud Anda tentang menjaga kondisi penjaga terlebih dahulu, tetapi kami tampaknya tidak setuju pada urutan masalah yang berbeda ini harus diprioritaskan. ;)
ilkkachu
@ilkkachu Ya, mungkin kami tidak setuju tentang itu. Di sisi lain, saya mulai menulis jawaban ini setelah mook765 sudah diposting dan OP telah menandainya sebagai diterima. Jadi saya memutuskan untuk memulai jawaban ini dengan merujuk ke jawaban itu (" mook765 sepenuhnya benar tentang penyebab masalah, dan solusi yang diajukan dalam jawaban itu memperbaiki kesalahan sintaks") sebelum kemudian membuat sebagian besar sisa jawaban saya tentang solusi alternatif menempatkan mereka di tempat lain daripada bagian paling atas file.
Eliah Kagan
2
@ cek Terima kasih atas sarannya - Saya telah menambahkan beberapa catatan akhir untuk membahas hal itu dan beberapa masalah terkait, bagi pembaca yang tertarik. (Alasan saya tidak menganggap ~/.bashrcsumber ~/.bash_aliasesmenjadi poin yang sangat penting dalam konteks ini adalah bahwa pemeriksaan ~/.bashrcfile OP mengungkapkan bahwa kode yang melakukannya tetap utuh. Namun, keduanya relevan dan menarik, dan Anda hak untuk menyarankannya disebutkan.)
Eliah Kagan