내가 다음과 같은 영리한 스크립트를 작성한다고 가정해 보겠습니다 rsh.sh
.
#!/usr/bin/env bash
git_project=`git rev-parse --show-toplevel`
git_prefix=`git rev-parse --show-prefix`
name=$(basename '${git_project}')
ssh $1 "cd '${name}' && $2"
내 CLI에서는 다음과 같이 썼습니다.
$: rsh.sh vm ls
(작동한다고 가정하고 오타는 제쳐두세요)
rsh.sh
다음으로 명령 프롬프트와 동일하며 큰따옴표 및 작은따옴표 기술을 완전히 자유롭게 활용할 수 있다고 가정합니다 .
# and maybe I'll have to add more escapes
$: rsh.sh vm "cat foo | awk -f '{print(\"bar\")}'"
# but ideally I could skip all that, not parse the cmd string using bash, and write
$: rsh vm cat foo | awk -f '{print("bar")}'
# however, here, the command will be partitioned by the "|" symbol, and only the
# first clause is going to be evaluated by the script
따라서 문제는 간단하고 우아하게(즉, 많은 기호 수정이 발생해야 하는 경우 "이 작업을 수행하기 위한 특수 도구를 작성"하는 것이 답일 수 있음) 명령줄에서 제공하는 리터럴 명령을 필드에 채우는 방법입니다. 예를 들어, ssh
3개월 후에 모든 것이 사용자(나)가 기대하는 대로 작동하도록 명령에서? (필요한 모든 이스케이프 문자를 고려)
지금까지 제가 생각해낸 복잡한 솔루션은 cli 입력 데이터를 가져와서 파일에 저장하는 간단한 문제를 해결하는 것입니다.
- cli 문자열(파이프 문자 포함)의 전체 내용을 소화하는 알려지지 않은 방법 찾기
- 이 내용을 tmp 디렉토리의 쉘 스크립트에 넣으십시오.
- 이 쉘 스크립트를 해시된 이름을 사용하여 원격 시스템으로 scp합니다.
ssh
문자 이스케이프를 관리하는 대신 이 쉘 스크립트를 실행하십시오.
그러나 이상적으로는 CLI 문자열을 지정하고 이를 ssh 큰따옴표 절에 넣고 이스케이프 문자가 올바르게 평가되도록 하는 방법이 있습니다.
마음에 떠오르는 도구는 m4
, tmp
및 sponge
이지만, 명령을 문자열 리터럴로 소화하고 행을 포함하지 않고 명령 문자열에 표시하는 방법을 여전히 알아낼 수 없습니다 ssh
.bash
#!/bin/bash
답변1
무엇을 위해제 생각에는이것이 실제 문제입니다(=확장되지 않은 원시 명령줄을 가져와서 다른 명령에 인수로 전달합니다.), "별칭 + 주석 + 기록" 트릭을 사용할 수 있습니다. 이 트릭은 여기와 stackoverflow에서 많은 답변을 찾을 수 있습니다.
alias ush='_ush #'
_ush(){
local l=$(fc -nl -0) # get the current command line from history
l=${l#*ush} # strip it up to and including the name of the alias (ush)
l=${l#"${l%%[! ]*}"} # strip any spaces after the name of the alias
local h=${l%% *} # get the user@host part of the command
l=${l#"$h"} # get the rest of the command line
ssh "$h" "$l" # run the above verbatim on user@host
}
ush user@host echo foo > file
# will create "file" on the remote host
ush user@host foo | bar
# will run both foo and bar on the remote host
!!
참고: bash는 bash 소스 코드를 수정하거나 readline 코드에 직접 연결하지 않고 앞머리 이후에 별칭을 확장합니다("역사적 확장") . 확장하기 전에 명령줄을 얻을 수 있는 방법은 없습니다 . !:$
해당 기능을 적극적으로 사용하지 않는 경우(대부분 형식적으로) 안전하게 끄기 를 사용할 수 있습니다 set +H
.