Cara menggunakan variabel lingkungan di dalam string yang dikutip di Bash

95

Saya telah mencoba berbagai bentuk berikut dalam skrip bash:

#!/bin/bash
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Tetapi saya tidak bisa mendapatkan sintaks untuk memperluas COLUMNSvariabel lingkungan dengan benar .

Saya sudah mencoba berbagai bentuk berikut ini:

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W $COLUMNS'

dan

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W ${COLUMNS}'

dan

eval svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Saran?

Jamie
sumber
jadi apa yang dihasilkan contoh-contoh itu dalam kasus Anda? Dan apa yang Anda ingin mereka hasilkan?
perintah di luar skrip berfungsi?
dfa
Sudahkah Anda mencobasvn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W ""$COLUMNS"
Qian Chen
BTW, menggunakan tanda $@kutip membuatnya persis sama dengan $*- artinya ia memecah "foo bar"menjadi dua argumen terpisah, foodan bar. Jika Anda ingin mempertahankan daftar argumen asli seperti yang diberikan kepada Anda, Anda menginginkannya "$@".
Charles Duffy

Jawaban:

16

Jika tidak yakin, Anda dapat menggunakan permintaan 'cols' di terminal, dan lupa KOLOM:

COLS=$(tput cols)
TheBonsai
sumber
Untuk alasan apa pun, ini adalah satu-satunya solusi yang dapat saya kerjakan dari halaman ini (per 11 / Mei 10:38 ET). Terima kasih
Jamie
407

Sekadar catatan / ringkasan singkat untuk siapa saja yang datang ke sini melalui Google mencari jawaban atas pertanyaan umum yang ditanyakan dalam judul (seperti saya). Salah satu dari berikut ini seharusnya berfungsi untuk mendapatkan akses ke variabel shell di dalam tanda kutip:

echo "$VARIABLE"
echo "${VARIABLE}"

Penggunaan tanda kutip tunggal adalah masalah utama. Menurut Manual Referensi Bash :

Karakter yang dimasukkan dalam tanda kutip tunggal ( ') mempertahankan nilai literal dari setiap karakter di dalam tanda kutip. Kutipan tunggal tidak boleh muncul di antara tanda kutip tunggal, bahkan jika diawali dengan garis miring terbalik. [...] Melampirkan karakter dalam tanda kutip ganda ( ") mempertahankan nilai literal dari semua karakter dalam tanda kutip, dengan pengecualian $, `, \, dan, ketika ekspansi sejarah diaktifkan, !. Karakter $dan `pertahankan arti khususnya dalam tanda kutip ganda (lihat Ekspansi Shell). Backslash mempertahankan arti khusus hanya ketika diikuti oleh salah satu karakter berikut: $, `, ",\, atau baris baru. Dalam tanda kutip ganda, garis miring terbalik yang diikuti oleh salah satu karakter ini akan dihapus. Garis miring terbalik karakter sebelumnya tanpa arti khusus dibiarkan tidak dimodifikasi. Kutipan ganda dapat dikutip dalam tanda kutip ganda dengan mendahului dengan garis miring terbalik. Jika diaktifkan, perluasan riwayat akan dilakukan kecuali !kemunculan dalam tanda kutip ganda di-escape menggunakan garis miring terbalik. Garis miring terbalik sebelum !tidak dihapus. Parameter khusus *dan @memiliki arti khusus ketika dalam tanda kutip ganda (lihat Ekspansi Parameter Shell).

Dalam kasus khusus yang ditanyakan dalam pertanyaan, $ COLUMNS adalah variabel khusus yang memiliki properti tidak standar (lihat jawaban lhunath di atas).

RekursifIronik
sumber
20
Dalam kasus tanda kutip tunggal, mungkin solusi ini membantu: 'before'"$variable"'after'(seperti yang dinyatakan dalam jawaban ini: stackoverflow.com/a/13802438/2254346 )
MakisH
Jawaban yang bagus! Saya memiliki masalah yang sama saat merujuk variabel env saya dalam tanda kutip tunggal. Setelah saya mengubah kutipan tunggal saya menjadi tanda kutip ganda, variabel env saya diperluas seperti yang diharapkan.
Binita Bharati
14

Perhatikan bahwa COLUMNS:

  1. BUKAN variabel lingkungan. Ini adalah parameter bash biasa yang diatur oleh bash itu sendiri.
  2. Diatur secara otomatis setelah menerima SIGWINCHsinyal.

Poin kedua itu biasanya berarti bahwa COLUMNSvariabel Anda hanya akan disetel di shell interaktif Anda , bukan di skrip bash.

Jika skrip Anda stdinterhubung ke terminal Anda, Anda dapat secara manual mencari lebar terminal Anda dengan menanyakan terminal Anda:

tput cols

Dan untuk menggunakan ini dalam perintah SVN Anda:

svn diff "$@" --diff-cmd /usr/bin/diff -x "-y -w -p -W $(tput cols)"

(Catatan: Anda harus mengutip "$@" dan menjauh dari eval;-))

lhunath
sumber
Terima kasih untuk informasi; mengetahui apa yang terjadi membawa perasaan katarsis pada masalah tersebut.
Jamie
2

Skrip berikut berfungsi untuk saya untuk beberapa nilai $COLUMNS. Saya ingin tahu apakah Anda tidak mengatur COLUMNSsebelum panggilan ini?

#!/bin/bash
COLUMNS=30
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Dapatkah Anda menggemakan $COLUMNSdi dalam skrip Anda untuk melihat apakah itu disetel dengan benar?

Alex B
sumber
Boo, hiss re: unquoted $@- yang membagi satu parameter "two words"menjadi dua parameter terpisah, twodan words. Harus "$@"melewati daftar argumen persis seperti yang diberikan.
Charles Duffy
0

Anda melakukannya dengan benar, jadi saya rasa ada hal lain yang salah (bukan mengekspor KOLOM?).

Trik untuk men-debug kasus ini adalah dengan membuat perintah khusus (penutupan untuk orang bahasa pemrograman). Buat skrip shell bernama diff-kolom melakukan:

exec /usr/bin/diff -x -y -w -p -W "$COLUMNS" "$@"

dan gunakan saja

svn diff "$@" --diff-cmd  diff-columns

Dengan cara ini kode Anda lebih bersih untuk dibaca dan lebih modular (pendekatan top-down), dan Anda dapat menguji kode kolom-diff secara terpisah (pendekatan bottom-up).

Colas Nahaboo
sumber
Baris perintah diurai sebelum proses bercabang, jadi tidak mengekspor COLUMNS tidak akan menjadi masalah.
Peter van der Heijden
1
Dia mengatakan kodenya di bagian dari skrip bash, jadi itu bisa menjadi masalah.
Colas Nahaboo