programing

(colon) GNU Bash 빌트인의 목적은 무엇입니까?

closeapi 2023. 4. 21. 20:53
반응형

(colon) GNU Bash 빌트인의 목적은 무엇입니까?

코멘트 리더에 지나지 않고 실제로는 셸이 내장되어 있는 명령어의 목적은 무엇입니까?

스크립트에 코멘트를 삽입하는 것보다 콜당 약 40% 느립니다.이것은 코멘트의 크기에 따라 크게 다를 수 있습니다.생각할 수 있는 이유는 다음과 같습니다.

# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done

# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command

# an alias for `true'
while : ; do command ; done

내가 정말로 찾고 있는 것은 그것이 어떤 역사적 응용을 가지고 있었을까 하는 것이다.

역사적으로, 본 포탄에는true ★★★★★★★★★★★★★★★★★」false명령어로 지정합니다. true 를 붙였습니다.: , , , , 입니다.false과 같은 let 0.

: true고대 본에서 유래한 조개껍데기로의 이동성을 위해.예로서 「」를 않는 해 주세요.! 파이프라인 오퍼레이터||('Bourne' 목록 연산자). 이 the가 .elseif종료 상태에 따라 분기하는 유일한 수단으로서의 스테이트먼트:

if command; then :; else ...; fi

★★if에는 공백이 「」가 합니다.then이 아닌 것으로 간주되지 .:무수술로 기능합니다.

오늘날(즉, 현대적 맥락에서)에는 보통 다음 중 하나를 사용할 수 있습니다.: ★★★★★★★★★★★★★★★★★」true 다 POSIX에 되며, 것은 POSIX를 찾기도 어떤 은 POSIX를 찾기도 합니다.true그런데 재미있는 있어요.:는 이른바 POSIX 스페셜 빌트인입니다만,true표준 내장입니다.

  • 셸에 특수 빌트인을 삽입해야 합니다.일반 빌트인은 "일반적인" 빌트인일 뿐, 엄밀하게 보증되는 것은 아닙니다. 정규 에는 '이렇게 하면 안 돼요'라는 이름이 붙으면 안 요.:truePATH를 사용하다

  • 아마도 가장 중요한 차이점은 ksh93을 사용하여 보여지듯이 특별한 빌트인을 사용하면 빌트인에 의해 설정된 모든 변수가 명령어 완료 후에도 유지된다는 것입니다.

    $ unset x; ( x=hi :; echo "$x" )
    hi
    $ ( x=hi true; echo "$x" )
    
    $
    

    Zsh는 POSIX 호환성 모드로 동작하는 경우를 제외하고 GNU Bash와 마찬가지로 이 요건을 무시하지만 대시, ksh93 및 mksh를 포함한 다른 모든 주요 "POSIX sh derived" 셸에서는 이를 감시합니다.

  • 또 다른 차이점은 일반 빌트인은 다음 제품과 호환성이 있어야 한다는 것입니다.exec서 Bash를 : - "Bash"를 사용합니다.

    $ ( exec : )
    -bash: exec: :: not found
    $ ( exec true )
    $
    
  • 는 또한 POSIX가 POSIX에 대해 하고 있습니다.:true물론 이것은 실장 고유의 상세입니다.

변수 명령을 쉽게 활성화/비활성화하기 위해 사용합니다.

#!/bin/bash
if [[ "$VERBOSE" == "" || "$VERBOSE" == "0" ]]; then
    vecho=":"     # no "verbose echo"
else
    vecho=echo    # enable "verbose echo"
fi

$vecho "Verbose echo is ON"

따라서

$ ./vecho
$ VERBOSE=1 ./vecho
Verbose echo is ON

이렇게 하면 깔끔한 대본이 됩니다.이 작업은 '#'에서는 수행할 수 없습니다.

또한.

: >afile

는 'file'이 존재하지만 길이가 0임을 보증하는 가장 간단한 방법 중 하나입니다.

「 」의 편리한 .:명령어에 결과를 전달하는 대신 부작용에 대한 매개변수 확장만 사용하려는 경우입니다.

합니다.: ★★★★★★★★★★★★★★★★★」false종료 상태가 0인지 1인지에 따라 달라집니다.예를 들면 다음과 같습니다.

: "${var:=$1}"

★★:기본 제공이므로 꽤 빠를 것입니다.

:블록 코멘트용으로도 사용할 수 있습니다(C 언어의 /* * / 와 유사).예를 들어 스크립트에서 코드 블록을 건너뛰는 경우 다음을 수행할 수 있습니다.

: << 'SKIP'

your code block here

SKIP

다른 답변에서 언급하지 않은 두 가지 용도:

로깅

다음 예제 스크립트를 사용합니다.

set -x
: Logging message here
example_command

번째 줄, 첫 번째 줄, 첫 번째 줄,set -x는 셸이 명령어를 실행하기 전에 명령어를 출력하도록 합니다.을 사용하다의 점점름름 름름름 the the the the the the the echo Log message스테이트먼트 타입에 의해, 메세지가 2 회 인쇄합니다.대장법은 그것을 회피할 수 있다. 점에 하시기 바랍니다.echo.

Cron 작업 제목

cron 작업에서 다음과 같이 사용되는 것을 본 적이 있습니다.

45 10 * * * : Backup for database ; /opt/backup.sh

이 작업은 cron 스크립트를 합니다./opt/backup.sh10시 45분입니다. 수 것입니다./opt/backup.sh몇 가지 출력을 출력합니다.

와와니다 it it to passPython 서 python 。

함수가 기록될 때까지 스텁아웃하는 것이 하나의 용도입니다.

future_function () { :; }

파일을 0바이트로 잘라 로그 지우기에 유용한 경우 다음을 수행하십시오.

:> file.log

backticks)과 할 수 .``하지 않고 과 같이

: `some_command`

.some_command > /dev/null ,는:좀 -버전이 짧다. -버전이 짧다.

그렇게 말하는 것은 사람들을 혼란스럽게 할 뿐이므로 실제로 그렇게 하는 것을 추천하지 않을 것이다.사용 가능한 사례로 생각했을 뿐입니다.

또한 다중 언어 프로그램에도 유용합니다.

#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
~function(){ ... }

이것은 이제 실행 가능한 셸 스크립트와 JavaScript 프로그램입니다.의미./filename.js,sh filename.js , , , , 입니다.node filename.js★★★★★★ 。

(확실히 조금 이상한 사용법이긴 하지만 그래도 효과적입니다.)


요청에 따른 설명:

  • 셸 는 한되며, 셸 스크립트는 한 줄씩 평가됩니다.exec명령어가 실행되면 셸이 종료되고 셸 프로세스가 결과 명령어로 대체됩니다.즉, 셸에서는 프로그램은 다음과 같습니다.

    #!/usr/bin/env sh
    ':' //; exec "$(command -v node)" "$0" "$@"
    
  • 워드에서 파라미터 확장이나 에일리어싱이 발생하지 않는 한 스크립트의 모든 워드는 의미를 변경하지 않고 따옴표로 묶을 수 있습니다.이는 다음과 같은 것을 의미합니다.':' :하는 JavaScript의 하기 위해 것 입니다.) (JavaScript는 따옴표로 묶은 것입니다.)

  • 와 같이 첫 , ...).그리고 위에서 설명한 바와 같이 첫 번째 줄의 명령어는 no-op입니다(즉,: // 말이 , 인용하고 싶은 말이 있다면요.':' '//' 점에 주의해 주세요.//자바스크립트그냥 버려지는 무의미한 단어일 뿐입니다.

  • 첫 줄에 두명령어( 뒤에 입니다.exec호출되는 셸 스크립트를 Node.js 프로세스로 대체하여 스크립트의 나머지 부분을 평가합니다.

  • JavaScript의행은 JavaScript)로 됩니다.':'그런 다음 삭제되는 코멘트를 입력합니다.자바스크립트

    ':'
    ~function(){ ... }
    

    string-literal은 그 자체로 회선상에 있기 때문에 no-op 스테이트먼트이며, 따라서 프로그램에서 삭제됩니다.즉, 회선 전체가 삭제되어 프로그램코드만 남습니다(이 예에서는,function(){ ... }

이 경우에도 하실 수 있습니다.:이치노

대본이 .mylib.sh하다.. mylib.sh그 를 호출합니다(즉, 함수는 호출됩니다lib_function1 arg1 arg2 않고 Library')를하여 라이브러리를 호출합니다.mylib.sh lib_function1 arg1 arg2를 참조해 주세요.

도 입력해 mylib.sh --help도움말 텍스트에 있는 기능 목록을 수동으로 유지 관리할 필요 없이 사용 가능한 기능 목록과 사용 방법을 얻을 수 있습니까?

#!/bin/bash

# all "public" functions must start with this prefix
LIB_PREFIX='lib_'

# "public" library functions
lib_function1() {
    : This function does something complicated with two arguments.
    :
    : Parameters:
    : '   arg1 - first argument ($1)'
    : '   arg2 - second argument'
    :
    : Result:
    : "   it's complicated"

    # actual function code starts here
}

lib_function2() {
    : Function documentation

    # function code here
}

# help function
--help() {
    echo MyLib v0.0.1
    echo
    echo Usage: mylib.sh [function_name [args]]
    echo
    echo Available functions:
    declare -f | sed -n -e '/^'$LIB_PREFIX'/,/^}$/{/\(^'$LIB_PREFIX'\)\|\(^[ \t]*:\)/{
        s/^\('$LIB_PREFIX'.*\) ()/\n=== \1 ===/;s/^[ \t]*: \?['\''"]\?/    /;s/['\''"]\?;\?$//;p}}'
}

# main code
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    # the script was executed instead of sourced
    # invoke requested function or display help
    if [ "$(type -t - "$1" 2>/dev/null)" = function ]; then
        "$@"
    else
        --help
    fi
fi

코드에 대한 코멘트:

  1. 모든 "public" 함수는 동일한 프레픽스를 가집니다.이들만 사용자에 의해 호출되어 도움말텍스트에 표시됩니다.
  2. 포인트에 하여 " " 를 합니다.declare -f사용 가능한 모든 함수를 열거한 다음 sed를 통해 필터링하여 적절한 접두사를 가진 함수만 표시합니다.
  3. 불필요한 확장 및 공백 제거를 방지하기 위해 문서를 작은 따옴표로 묶는 것이 좋습니다.또한 텍스트에서 아포스트로피/따옴표를 사용할 때도 주의해야 합니다.
  4. 프리픽스를 하기 위해 할 수 즉, 가 있는 것은 라이브러리 프리픽스입니다.mylib.sh function1으로는 ' 번역'이 .lib_function1이것은 독자에게 남겨진 연습입니다.
  5. 도와주다은 라이브러리 , ) 입니다.이 접근방식은 라이브러리 호출 메커니즘을 사용하여 "도움말가 없습니다.또한 추가 체크를 코드화할 필요가 없습니다.$1동시에 라이브러리의 소스를 지정하면 네임스페이스가 복잡해집니다.안 들면 을 '이름을 '이름을 ' 바꿔도 돼요'처럼 수 요.lib_help하여 "R"을 확인합니다.--help를 눌러 도움말 기능을 수동으로 실행합니다.

스크립트에서 이 사용법을 보고 스크립트 내에서 basename을 호출하는 것을 대신할 수 있다고 생각했습니다.

oldIFS=$IFS  
IFS=/  
for basetool in $0 ; do : ; done  
IFS=$oldIFS  

입니다.드드대대 대다다다다다basetool=$(basename $0)

여기서 아직 언급되지 않은 또 다른 방법은 무한 루프에서 매개변수를 초기화하는 것이다.아래는 가장 깨끗한 예는 아니지만 그 목적에 부합합니다.

#!/usr/bin/env bash
[ "$1" ] && foo=0 && bar="baz"
while : "${foo=2}" "${bar:=qux}"; do
    echo "$foo"
    (( foo == 3 )) && echo "$bar" && break
    (( foo=foo+1 ))
done

언급URL : https://stackoverflow.com/questions/3224878/what-is-the-purpose-of-the-colon-gnu-bash-builtin

반응형