Конвейер с псевдонимом, использующий head and cut

Я думаю, что вы не можете не жадный в поиск и замена, вы можете сделать это только с удалением подстроки. Из ссылок на bash:

${параметр/шаблон/строка}

Шаблон расширяется для получения образца так же, как при расширении имени файла. Параметр расширяется, и самое длинное совпадение шаблона с его значением заменяется на строку. Если шаблон начинается с '/', все совпадения шаблона заменяются строкой. Обычно заменяется только заменяется только первое совпадение. Если шаблон начинается с '#', то он должен совпадать в в начале расширенного значения параметра. Если шаблон начинается с '%', то он должен совпадать с концом расширенного значения параметра. Если строка равна null, совпадения с шаблоном удаляются, а символ /, следующий за шаблоном, может быть опущен. может быть опущен. Если параметр имеет значение '@' или '', операция подстановки применяется к каждому позиционному параметру по очереди, и расширением является результирующий список. Если параметр является переменной массива подписанная символом '@' или '', операция подстановки применяется к каждому члену массива по очереди, а расширением является результирующий список список.

Чтобы решить это, вы должны установить extglob:

shopt -s extglob
printf '%s\n' "${version/%.+([0-9])/.5}"
1.2.3.5

или использовать некоторые инструменты, такие как sed или perl:

printf '%s\n' "$version" | perl -pe 's/\.\d+$/\.5/'
1.2.3.5
4
21.02.2019, 19:29
2 ответа

aliasрасширение — это просто подстановка текста, которая снова анализируется оболочкой, поэтому, когда вы делаете:

thead file.csv

Это просто заменено на:

head | cut -d, -f1- | column -s, -t file.csv

и интерпретируется снова.

Если бы вы написали:

<file.csv thead

или

cat file.csv | thead

или

{ thead; } < file.csv

Он бы работал так, как если бы его заменили на:

<file.csv head | cut -d, -f1- | column -s, -t
cat file.csv | head | cut -d, -f1- | column -s, -t
{ head | cut -d, -f1- | column -s, -t; } < file.csv

соответственно. В любом случае, как говорит @Kusalananda, для этого гораздо лучше использовать функции или сценарии, чем псевдонимы. Здесь я бы просто сделал:

thead() { head "$@" | cut -d, -f1- | column -s, -t; }

Например, вы можете сделать thead -n 12 file.csv file2.csv.

10
27.01.2020, 20:45

Для чего-то более сложного, чем простая команда, используйте функцию оболочки вместо псевдонима:

thead () {
    head -- "$1" | cut -d, -f1- | column -s, -t
}

Эта функция оболочки будет запускать headсо своим первым аргументом, а затем отправлять результат по конвейеру (, хотя, поскольку cutполучает все столбцы из-за -f 1-, это часть, вероятно, можно удалить; Я оставлю это здесь, как это было в исходном конвейере ).

Или,

thead () {
    head -- "$2" | cut -d "$1" -f1- | column -s "$1" -t
}

... чтобы иметь возможность использовать его как

thead ',' filename

Или даже, чтобы разрешить необязательный разделитель (и использовать запятую, если она не указана ),

thead () {
    local delim=','

    if [ "$#" -gt 1 ]; then
        delim=$1
        shift
    fi
    
    head -- "$1" | cut -d "$delim" -f1- | column -s "$delim" -t
}

Приведенное выше определение функции можно разместить везде, где вы обычно определяете псевдонимы.


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


Руководство bashсодержит предложение

For almost every purpose, aliases are superseded by shell functions.

10
27.01.2020, 20:45

Теги

Похожие вопросы