Bash: Получение / Использование в последний раз (или Энный) строка в stdout

find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

ИЛИ

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

Здесь мы вычисляем количество согласующих отрезков длинной линии (использование -c) в файле, если количество 0 затем, это - необходимый файл, таким образом, мы сокращаем первый столбец т.е. имя файла от вывода.

11
13.04.2017, 15:36
4 ответа

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

Две функции, первые выполнения find с параметрами Вы передаете его, сохраняет вывод в массиве и отображает их. Вторым является просто помощник для доступа к тому массиву.

myfind() {
  IFS=$'\n' __last_find_result=($(find "$@"));
  printf "%s\n" "${__last_find_result[@]}";
}
myget() {
  echo "${__last_find_result[$1]}";
}

Вариант использования:

$ myfind . -name "c*"
./a b/c d
./.git/config
./.git/hooks/commit-msg.sample
$ vim "$(myget 0)"
# This opens the "./a b/c d" file.
$ vim "$(myget 2)"
# This opens ".git/hooks/commit-msg.sample"

Кавычки, не требуемые вокруг $(myget index) если у Вас нет пробела или других неприятных символов в Ваших именах файлов.
Продвигает целый вывод find к Вашей среде, которая могла бы быть ограничена. (Используя временный файл, а не тот массив решил бы это, но имеет другие проблемы - особенно параллельное использование от нескольких оболочек.)

8
27.01.2020, 19:58
  • 1
    я не могу upvote Вы, потому что у меня нет действительно репутации, таким образом, вот a, мм, словесный: "upvote" –  aaronlevin 28.12.2012, 20:00

У меня есть это в моем .screenrc:

bind -c pasteline 1 eval copy 'stuff "-Y"' 'paste .'
bind -c pasteline 2 eval copy 'stuff "2-Y"' 'paste .'
bind -c pasteline 3 eval copy 'stuff "3-Y"' 'paste .'
bind -c pasteline 4 eval copy 'stuff "4-Y"' 'paste .'
bind -c pasteline 5 eval copy 'stuff "5-Y"' 'paste .'
bind -c pasteline 6 eval copy 'stuff "6-Y"' 'paste .'
bind -c pasteline 7 eval copy 'stuff "7-Y"' 'paste .'
bind -c pasteline 8 eval copy 'stuff "8-Y"' 'paste .'
bind -c pasteline 9 eval copy 'stuff "9-Y"' 'paste .'
bindkey ¬ command -c pasteline

В основном, на экране, ¬1, вставляет строку выше курсора, ¬2, вставляет вторую строку выше курсора... и так далее. Можно хотеть добавить больше для строк 10 и выше, но я нахожу, что приблизительно после 7 уже, использовал бы мышь или screenрежим копии, чем подсчет количества строк для получения той я хочу.

6
27.01.2020, 19:58

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

#!/bin/bash

echo "enter your choice : z for last argument or a number for that file"
read choice

case "$choice" in
z) eval vim \$$#;;
*)eval  vim \$$choice;;
esac

сохраните этот сценарий с любым именем, говорят, "автонаходят" и вызывают сценарий с Ваш, "находят команду", поскольку аргументом здесь является код для вызова сценария:

./autofind `your find command`

Но перед использованием сценария проверяют Ваш, "находят команду", дает ли это результат или нет. Если это показывает, что некоторый результат затем только использует сценарий

0
27.01.2020, 19:58

Ответ Матса был именно тем, что я искал. Я немного расширил его код, чтобы у него было больше возможностей для получения.

$ f ~/scripts -name '*.sh'
$ vim $(g foo)  # edit all find results matching "foo"
$ vim $(g 1 3 5) # edit find results number 1, 3 and 5
$ vim $(g 3-5) # edit find results 3-5
$ vim $(g 5-) # edit find results 5 to last
$ vim $(g -7) # edit find result 7 from bottom
$ vim $(g 1 4-5 -7 9- foo) # all of the above combined

.

f() {
    IFS=$'\n' __last_find_result=($(find "$@"));
    printf "%s\n" "${__last_find_result[@]}";
}

g() {
    len=${#__last_find_result[@]}
    pad=${#len}
    numbers=""
    if [ "$1" == "-n" ]; then
        numbers=1
        shift
    fi
    if [ -z "$1" ]; then
        if [ -n "$numbers" ]; then
            n=1;
            for e in "${__last_find_result[@]}";do
                printf "%0${pad}d. %s\n" "$n" "$e"
                let n=n+1
            done
        else
            printf "%s\n" "${__last_find_result[@]}"
        fi
    else
        for l in $@;do
            if [[ "$l" =~ ([^0-9-]+) ]];then
                n=1;
                for e in "${__last_find_result[@]}";do
                    if [[ $e =~ $1 ]]; then
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "$e"
                        else
                            printf "%s\n" "$e"
                        fi
                    fi
                    let n=n+1
                done
            elif [[ "$l" =~ ^([0-9]+)$ ]];then
                let l=l-1
                echo "${__last_find_result[$l]}";
            elif [[ "$l" =~ ^([0-9]*)(-)?([0-9]*)$ ]]; then
                from=${BASH_REMATCH[1]};
                dash=${BASH_REMATCH[2]};
                to=${BASH_REMATCH[3]};
                if [ -z "$from" ]; then # -n
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    echo "${__last_find_result[-$to]}";
                else # n-m
                    [ -z "$to" ] && to=${#__last_find_result[@]}
                    [ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
                    let to=$to-1
                    let from=$from-1
                    n=$(($from+1))
                    for i in `seq $from $to`;do
                        if [ -n "$numbers" ];then
                            printf "%0${pad}d. %s\n" "$n" "${__last_find_result[$i]}"
                        else
                            printf "%s\n" "${__last_find_result[$i]}"
                        fi
                        let n=n+1
                    done
                fi
            fi
        done
    fi
}
0
27.01.2020, 19:58

Теги

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