Як я можу призначити результат команди змінній оболонки?


76

Я хочу призначити результат виразу змінній і з'єднати його з рядком, а потім повторити його. Ось що я маю:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

Але це виводить:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

Отже, схоже, що це не призначається $thefile, а друкується під час його виконання.


Відповіді:


108

Призначення оболонки - це одне слово, не маючи місця після знака рівності. Отже, те, що ви написали, присвоює порожнє значення thefile; крім того, оскільки призначення групується з командою, воно робить thefileзмінну середовища, і призначення є локальним для цієї конкретної команди, тобто лише виклик, щоб lsпобачити призначене значення.

Ви хочете зафіксувати результат команди, тому вам потрібно використовувати заміну команди :

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(Деяка література показує альтернативний синтаксис thefile=`ls …`; синтаксис зворотного котирування еквівалентний синтаксису дужок з дужками, за винятком того, що цитування всередині зворотних цитат іноді дивно, тому просто використовуйте $(…).)

Інші зауваження щодо вашого сценарію:

  • Поєднувати -t(сортувати за часом) з -U(не сортувати) не має сенсу; просто використовувати -t.
  • Замість того, щоб використовувати grepзіставлення скріншотів, чіткіше передавати підстановку lsта використовувати headдля зйомки першого файлу:

    thefile=$(ls -t *"Screen Shot"* | head -n 1)
  • Як правило, погана ідея розбору результатівls . Це може вийти з ладу, якщо у вас є імена файлів з недрукуваними символами. Однак, сортування файлів за датою важко ls, тому це прийнятне рішення, якщо ви знаєте, що у імен файлів не буде друкованих символів чи зворотних косих рисок.

  • Завжди використовуйте подвійні лапки навколо змінних підстановок , тобто тут пишіть

    echo "Most recent screenshot is: $thefile"

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

  • Вам не потрібні крапки з комою в кінці рядка. Вони зайві, але нешкідливі.
  • У сценарій оболонки часто корисно включити set -e. Це повідомляє оболонці вийти, якщо будь-яка команда не виконана (шляхом повернення ненульового стану).

Якщо у вас є GNU find (зокрема, якщо ви не працюєте з вбудованим Linux або Cygwin), є ще один підхід до пошуку останнього файлу: складіть findсписок файлів та їх дати, а також використовуйте sortта tailвитягайте наймолодший файл.

thefile=$(find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%T@ %p" |
          sort -k 1n | tail -n 1)

Якщо ви готові написати цей скрипт в zsh замість bash, існує набагато простіший спосіб знайти найновіший файл, оскільки zsh має глобальні класифікатори, які дозволяють підкреслити відповідність не лише на імена, але і на метадані файлів. (om[1])Частина після того, як шаблон відбіркові GLOB; omсортує відповідність за збільшенням віку (тобто за часом модифікації, найновішим першим) та [1]витягує лише перший збіг. Весь збіг повинен бути в дужках, оскільки це технічно масив, оскільки глобул повертає список файлів, навіть якщо [1]означає, що в цьому конкретному випадку список містить (максимум) один файл.

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
echo "Most recent screenshot is: $thefile"

7
Оце Так! Більше інформації, ніж я міг би сподіватися. Дякую багато разів за вашу відповідь; Я дуже ціную всі зусилля, які ви доклали до цього! Ти щойно показав мені, що мені дуже, дуже багато чого треба навчитися. Я збираюся купити книгу про bash: P.
Натан Г.

3
Саме так я б назвав остаточну відповідь! :)
alex

4

Якщо ви хочете зробити це за допомогою багаторядкових / декількох команд / с, ви можете зробити це:

output=$( bash <<EOF
#multiline/multiple command/s
EOF
)

Або:

output=$(
#multiline/multiple command/s
)

Приклад:

#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"

Вихід:

first
second
third

Це приємна відповідь. чи є спосіб я можу вказати змінну як частину команди? наприкладoutput=$(echo $someVariable)
Зак Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.