2013-08-21 2 views
2

Я написал скрипт (replace.sh), который заменяет ~ на ~ \ n. Мне было интересно, как я могу назвать этот скрипт несколькими аргументами.bash script: looping over arguments

#!/bin/bash 

for i in "$*" 
do 
    sed 's/~/~\n/g' "$i" 
done 

Например, я хотел бы позвонить ./replace.sh text1 text2. Он не может читать

содержимое text1 являются: 1 ~ 1 ~ 1. После вызова сценария он должен быть

1 ~ 
1 ~ 
1 ~ 
+0

Подробнее см. Здесь о различиях между '$ *' и '$ @': http://mywiki.wooledge.org/BashGuide/Parameters#Special_Parameters_and_Variables. Это тонкий, но очень важный для сценариев оболочки. – Telemachus

ответ

4

Использование "[email protected]" в вашей цикл:

for i in "[email protected]" 
do 
    sed -i.bak 's/~/~\n/g' "$i" 
done 

Хотя я не уверен, что sed делает то, что вы описали здесь.

+0

То, что мне нужно! Что касается sed, это должно быть 's/~/\\ n/g' – Paolo

+0

Сохраните несколько нажатий клавиш, не используя 'in '$ @" 'вообще ... – jlliagre

+1

@jiliagre Я думаю, что это случай, когда краткость хуже , Многие люди не будут знать, что означает «для i» в «$ @» '. Это 7 дополнительных символов, но выигрыш в ясности огромен. – Telemachus

2

Этого должно быть достаточно:

for i do 
    sed -i.bak 's/~/~\n/g' "$i" 
done 

Вот портативный вариант должен работать с любым совместимым shell POSIX и sed:

for i do 
    sed 's/~/~\n/g' "$i" > "$i.bak" && cp "$i.bak" "$i" 
done 

Примечание: В in ... часть оболочки for петли является необязательным. Когда не используется, for по умолчанию выбирает все аргументы (т. Е. "[email protected]"), что и есть то, что вы ожидаете.

+1

Пожалуйста, не рекомендуем '-i' без суффикса. Это означает отсутствие резервных копий. Нет резервных копий -> скорее всего ой. Кроме того, возможно, объясните, что это означает, если вы используете цикл 'for' в скрипте оболочки без' in '? – Telemachus

+0

Ответ обновлен с помощью более портативного решения (POSIX), которое обрабатывает примечание о резервном копировании, хотя запуск сценария более одного приведет к файлам xxx.bak.bak, в то время как первый запуск перезапишет потенциальные существующие резервные копии ... – jlliagre

+1

@jiliagre +1 Спасибо за обновление/уточнение. (Я слышал, что вы на нескольких трассах, но по-прежнему считаете, что всегда стоит упомянуть «.bak» для новых сценаристов. Моя проблема с моей машиной с тех пор, как я впервые узнал о Perl с одним лайнером. – Telemachus

1

Другие ответы охватывают вашу настоящую проблему. Но одно стоит сказать больше о том, как $* и [email protected] отличаются расширением при двойном цитировании. tl; dr Вы почти всегда хотите "[email protected]".

"$*" расширяется до одной строка, содержащей все параметры с первым символом в IFS между ними. На практике это обычно означает, что все параметры являются одной строкой, разделенной пробелами. Итак, если ваши параметры: file1.txt, file2.txt и file3.txt, то "$*" руки, которые соответствуют петле как одна вещь, а именно file1.txt file2.txt file3.txt. Это одно, конечно, не существует как таковое.

"[email protected]" расширяет до каждый из параметров, по одному, рассматривается как одно слово «слово». Это хорошо, потому что он будет обрабатывать file1.txt, file2.txt и file3.txt из предыдущего примера правильно, так как три предмета. Цикл будет принимать их правильно по одному за раз. Кроме того, "[email protected]" хорош, так как даже если ваши имена файлов имеют пробелы в них, вы получите правильное поведение, так как цикл будет обрабатываться, например. filename 1, filename 2, filename 2 and a half как три предмета, один за другим. (Обычно оболочка рассматривает пространство как маркировка конца слова, так filename 1 будет выглядеть два пунктов к оболочке, filename и 1.

Когда они не указаны как [email protected] и $* расширить слова все позиционные параметры. Таким образом, в этом случае они фактически идентичны (и плохая идея, так как они не защищают вас от странно названных файлов).

Здесь есть хорошая визуализация всех возможностей: http://wiki.bash-hackers.org/scripting/posparams#mass_usage.

+0

вы должны включить двойные кавычки в свой ответ, так как эти две переменные также имеют смысл (идентичные значения, фактически), если они не кавычки. Вы также можете захотеть охватить нецифровые значения в ответе. В его основе: _' $ * 'расширяется до одна строка_ является неправильной, она должна быть '' '$ *" 'расширяется до одной строки_ ... Да, вы упомянули двойные кавычки в предыдущем абзаце, но опускать их в следующем вводит в заблуждение. –

+0

@JonathanLeffler Вы абсолютно правильно. Не уверен, что со мной не так. Я должен включить цитаты, и я упомянул о некорректных версиях. – Telemachus

+0

Эй, телемаш. У меня было ощущение, что «$ *» расширилось до одной строки, спасибо за подтверждение и объяснение что происходило за кулисами. – Paolo