Код интерпретации сценария оболочки и параметры

У меня есть следующий сценарий оболочки, и они спрашивают меня, как работает и каковы параметры $ 1 и $ 2.

#!/bin/bash

for i in `sort $1`; do   
    if grep $2 $i > /dev/null; then 
        echo A  
        cp $i /tmp  
        exit  
    fi  
done  
echo B;

Мой вопрос таков: $ 1 не может быть каталогом, потому что вы не можете сортировать по каталогам. Следовательно, это должен быть файл. Но функция «for i in file» подразумевает, что мы будем работать для каждой строки, а инструмент grep не работает со строками.

Я считал, что это должен быть файл, содержащий файлы, но пока я могу думать только о файлах tar, и он не работает с ними.

Спасибо!

Don'tReadLinesWithFor - этот код по сути не работает. См. BashFAQ # 1 для получения рекомендаций по построчному чтению файлов.
Charles Duffy 28.03.2018 18:26

(Тем не менее, строчно-ориентированные файлы в целом не могут безопасно использоваться для хранения списков произвольных имен файлов, потому что файлы могут иметь имена, содержащие символы новой строки. Единственное безопасное хранилище - для произвольных имен файлов, таких как произвольные строки C, переменные среды и т. д. разделен NUL).

Charles Duffy 28.03.2018 18:27

Кроме того, непонятно, о чем вы на самом деле спрашиваете. Это для объяснения того, как работает этот код? У него не работает корректно - битый. (Более того, чем я уже описал - если у вас есть * в виде строки в вашем файле, она будет заменена списком всего в вашем текущем рабочем каталоге).

Charles Duffy 28.03.2018 18:28

... вы говорите: «У меня такой вопрос», но то, что следует далее, является утверждением, а не вопросом.

Charles Duffy 28.03.2018 18:29

Также см. Что делать с вопросами типа «Я не понимаю, как работает этот код?» в Meta StackOverflow - консенсус состоит в том, что такие вопросы следует закрывать как «непонятно, о чем вы спрашиваете» или «слишком широко».

Charles Duffy 28.03.2018 18:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

sort $1, скорее всего, означает, что $1 содержит путь к файлу. Скорее всего, содержимое файла - это пути к другим файлам. В его некотируемой форме он будет подвергаться разбиению на слова и расширению глобуса. Это либо недосмотр, либо предполагаемое поведение (например, он расширит 'dat?.lst' до списка файлов, как указано в комментариях).

Цикл for предполагает, что ни один из этих путей не содержит каких-либо неудобных символов (пробелов, глобальных символов, таких как *), и просматривает каждое слово в отсортированном выводе.

$2 (который на самом деле должен быть "$2") - это шаблон для поиска в файле $i. Если содержимое файла соответствует шаблону, файл копируется на /tmp, и сценарий завершается.

Учитывая предостережение не работать с именами файлов, содержащими символы новой строки, самым простым исправлением было бы:

#!/bin/bash

sort "$1" | while read -r file; do
    if grep -q "$2" "$file" 2>/dev/null; then
        echo A  
        cp "$file" /tmp  
        exit  
    fi
done

Это предполагает, что скрипту передается путь к файлу в качестве первого аргумента, например:

/path/to/first/file
/path/to/second/file

И регулярное выражение в качестве второго аргумента с экранированием $, чтобы оболочка не пыталась их расширить.

Изменяет ли $ 1 или "$ 1" семантику программы. Может быть, автор хочет передать "dat? .Lst" в качестве параметра, который нужно расширить?

user unknown 28.03.2018 18:50

@userunknown: тогда это был бы действительно неудобный интерфейс. В этом случае сценарий должен обрабатывать несколько аргументов и позволить оболочке выполнить подстановку; тогда лучше перепроектировать интерфейс, используя шаблон в качестве первого аргумента, а оставшимися аргументами будут файлы. Тогда использование будет script thing-to-match file1 file2 file3 и разрешить script thing-to-match dat?.lst.

gniourf_gniourf 28.03.2018 19:05

@userunknown: поскольку автор сценария даже не удосужился процитировать расширение $2 для оператора grep, я бы сказал, что это скорее ошибка сценариста, чем фактическая особенность дизайна.

gniourf_gniourf 28.03.2018 19:07

@gniourf_gniourf: AFAIK, вопрос - это вопрос интервью, где вы должны ответить, что делает сценарий, а не как его улучшить.

user unknown 28.03.2018 19:17
!/bin/bash

for i in `sort $1`  
do   
if grep $2 $i > /dev/null  
    then 
         echo A  
         cp $i /tmp  
         exit  
    fi  
done  
echo B;

Вероятно, первый параметр - это имя файла или список имен файлов без пробелов, который сам содержит список имен файлов. $ 2 - это ключевое слово, которое ищется в этих файлах, которые сначала были отсортированы по имени.

Первое совпадение приводит к копированию этого файла в / tmp - вероятно, для дальнейшей обработки, а также к эхо-сообщению A и завершению программы. Если соответствующий файл не найден, печатается другое сообщение.

Обратите внимание, что маскировка $ 1 выглядит следующим образом:

for i in $(sort "$1")
do   

предотвратит распространение подстановочных знаков,

script "dat-?.lst" foobar

и, возможно, сломать сценарий, поэтому я буду осторожен с предложениями по его улучшению.

Другие вопросы по теме