Bash: 명령줄에서 한 번의 호출로 파일의 모든 기능을 호출하는 방법은 무엇입니까?

Bash: 명령줄에서 한 번의 호출로 파일의 모든 기능을 호출하는 방법은 무엇입니까?

저는 Bash와 함께 Ubuntu 16.04를 사용하고 있으며 10개의 기능이 포함된 파일이 있습니다. 각 기능은 본질적으로 다른 작업을 수행합니다. 각 함수의 끝에서 다음과 같이 호출합니다.

x() {
    echo
}
x

이 호출은 파일에 10줄을 더 추가하는데, 미학적 이유로 파일에서 저장하고 싶습니다. 어쨌든 파일의 모든 기능을 (이미 정렬된 순서대로) 실행할 것이기 때문입니다.

물론, 단지 소싱(현재 세션에서 실행)이나 배싱(하위 세션에서 실행)만으로는 충분하지 않습니다(때때로 사람들이 source/bash 모든 기능을 실행하지 않음).

이 작은 미학적 문제에 대해 내가 선호하는 해결책은 파일의 소스/공격 이후에 명령줄에서 직접 모든 기능을 호출하는 것입니다.

배쉬에서 가능합니까?

답변1

파일의 줄 수에만 관심이 있는 경우 다음을 수행할 수 있습니다.

my_func () {
    echo "Hello, world"
} && my_func

답변2

당신은 그것을 사용할 수 있습니다 :

source <(declare -f | grep -o '^[[:alnum:]]\+')

이는 범위(declare -fgrep -o '^[[:alnum:]]\+'), 그런 다음 왼쪽 여백( )에 있는 유일한 영숫자 문자열 인 이름만 필터링하고 마지막으로 다음과 같이 한 줄에 하나씩 함수 이름 목록인 결과 출력을 얻습니다.프로세스 교체이렇게 하면 현재 쉘에서 모두 호출됩니다.

위 내용은 을 grep사용하는 GNU 또는 BSD 에 적용되지만 필요한 경우 -o적절한 또는 명령으로 전환할 수 있습니다 .sedawk


여기의 함수는 특별한 순서가 없습니다(Bash의 해시 테이블 순서는 본질적으로 무작위라고 생각합니다). 순서를 유지해야 하는 경우 적절하게 이름을 지정하고 sort중간에 추가하세요.

source <(declare -f | grep -o '^[[:alnum:]]\+'|sort)

함수 자체를 독립적으로 호출하려는 경우 이 명명 구조는 바람직하지 않을 수 있습니다. 쉬운 해결책이 보이지 않습니다.


이는 단일 파일 내에서 작동합니다. 이미 함수가 정의된 셸로 파일을 가져오는 경우 이미 존재하는 함수를 기억하고 건너뛰어야 합니다.

funcs=($(declare -f | grep -o '^[[:alnum:]]\+'|sort))
source file
source <(declare -f | grep -o '^[[:alnum:]]\+' | sort - <(printf '%s\n' "${funcs[@]}" | uniq -u)

이를 수행하는 방법에는 몇 가지가 있지만 모두 매우 어색합니다. 기존 함수를 재정의하는 경우에도 실패합니다. 또 다른 접근 방식은 파일 자체에서 모든 함수 정의 라인을 가져오는 것입니다 grep. 작성 방법을 구성하는 경우에도 작동합니다.


파일 내용을 제어하는 ​​경우 파일 하단의 한 줄 배열 정의에 호출하려는 순서대로 함수 이름을 나열하는 것이 더 나을 수 있습니다. 그런 다음 소스 셸에서 이를 반복하여 필요한 작업을 수행할 수 있습니다.

이 접근 방식은 더 명확하고 덜 취약합니다. 그러나 두 위치가 동기화되지 않을 가능성이 있습니다.

답변3

정말로 한 줄을 원한다면 파일이 있다고 가정하고 이것을 생각해 냈습니다 scripts/1.sh.

shopt -s extdebug; source scripts/1.sh; source="$_"; while IFS= read -r func; do declare_output="$(declare -F "${func##* }")"; [[ ${declare_output##* } == $source ]] && "${func##* }"; done < <(declare -F)

declare기본적으로 이는 환경의 어떤 기능이 소스 파일에서 나오는지 확인하고 실행하는 데 사용됩니다 . scripts/1.shecho Goodbye, cruel및 의 세 가지 기능이 있으며 world.이 명령의 출력은 다음과 같습니다.

Goodbye,
cruel
world.

declare출력 순서가 함수가 소싱된 순서대로 보장 되는지 모르므 로 함수 이름을 적절하게 지정하고 sort.

답변4

여러 가지 이유로 명시적인 통화를 유지하는 것이 좋습니다. 호출 목록에서 특정 기능을 일시적으로 제거하고, 순서를 변경하고, 편집할 때 이전 버전의 기능을 유지하고, 다른 기능만 호출하는 유틸리티 기능을 사용할 수 있습니다("기본" 수준에서는 호출하지 않음). 마지막 것은 프로그램의 올바른 구성에 특히 중요한 것 같습니다.


하지만 정말로 원한다면 할 수 있습니다. 적어도 자동으로 실행될 수 있는 기능에 대한 일종의 표시기를 추가하는 것이 좋습니다. 부분적으로 @cas의 의견을 바탕으로 # AUTORUN위 줄에 표시된 모든 기능이 실행됩니다.

#!/bin/bash

foo() { echo foo; }

# AUTORUN
bar() { echo bar; }

while IFS= read -r f; do
    $f
done < <(sed -nE '/^# *AUTORUN/!d; n; s/^([a-zA-Z0-9_]+) *\(\).*/\1/p' "${BASH_SOURCE[0]}")

현재 형식의 GNU sed가 필요할 수 있습니다.

관련 정보