2014-11-23 3 views
0

원격 시스템에서 Java 기반 CLI 메뉴를 탐색하면서 bash 스크립트를 사용하고 예상 세션을 떠나지 않고 출력에서 ​​추출하려고합니다.Expect : 출력에서 ​​특정 문자열을 추출하십시오.

내 스크립트 명령은 예상 :

expect -c " 
spawn ssh [email protected] 
expect \"#\" 
send \"java cli menu command here\r\" 
expect \"java cli prompt\" 
send \"java menu command\" 
" 
###I want to extract a specific string from the above output### 

기대 출력은 다음과 같습니다

Id  Name 
------------------- 
abcd 12 John Smith 

나는 다른에 위의 출력에서 ​​abcd 12을 추출 할 것으로 예상 스크립트 내 추가 사용에 대한 변수를 기대합니다. 그래서 그것은 두 번째 공백 구분 기호를 사용하여 첫 번째 필드 인 세 번째 줄입니다. awk 등가물은 다음과 같습니다. awk -F ' ' 'NR==3 {$1}'

큰 문제는 위에서 언급 한 것처럼 Expect로 탐색하는 환경이 Java CLI 기반 메뉴이므로 awk 또는 다른 것을 사용할 수는 없습니다. bash 쉘에서 사용할 수 있습니다.

로그인 과정이 15 초 동안 지속되므로 출력을 처리 한 다음 다시 입력하는 것은 옵션이 아니므로 내부에 있어야하며 내부 명령 만 사용하여 출력에서 ​​필요한 항목을 추출해야합니다. .

+0

핵심 문제는 expect 스크립트를 큰 따옴표로 묶은 쉘 리터럴에 넣으려고한다는 것입니다. 그것은 당신에게 백 슬래시 인용문을 사용하도록 강제 할 것입니다. 그렇게 할 수있는 동안 expect 스크립트를 자신의 파일 (예 :'mydostuff.exp')에 넣으면 모든 것이 훨씬 간단 해집니다. 'expect mydostuff.exp'로 실행할 수 있습니다 ... –

답변

4

-re 플래그를 직접 사용하여 expectregexp을 직접 사용할 수 있습니다. 작은 따옴표와 큰 따옴표 문제를 지적한 Donal에게 감사드립니다. 나는 두 가지 방법으로 해결책을 제시했다. 다음과 같이 내가 내용을 가진 파일을 만든

Id  Name 
------------------- 
abcd 12 John Smith 

이 아무것도하지만 자바 프로그램의 콘솔 출력되지 않습니다. 나는 이것으로 나의 시스템에서 이것을 테스트했다. 즉, 방금 cat을 사용하여 프로그램의 출력을 시뮬레이션했습니다. cat 코드를 프로그램 명령으로 바꿉니다. 단순한. :)

따옴표 :

#!/bin/bash 
expect -c " 
spawn ssh [email protected] 
expect \"password\" 
send \"mypassword\r\" 
expect {\\\$} { puts matched_literal_dollar_sign} 
send \"cat input_file\r\"; # Replace this code with your java program commands 
expect -re {-\r\n(.*?)\s\s} 
set output \$expect_out(1,string) 
#puts \$expect_out(1,string) 
puts \"Result : \$output\" 
" 

단일 따옴표 : 당신이 볼 수 있듯이

#!/bin/bash 
expect -c ' 
spawn ssh [email protected] 
expect "password" 
send "mypasswordhere\r" 
expect "\\\$" { puts matched_literal_dollar_sign} 
send "cat input_file\r"; # Replace this code with your java program commands 
expect -re {-\r\n(.*?)\s\s} 
set output $expect_out(1,string) 
#puts $expect_out(1,string) 
puts "Result : $output" 
' 

, 나는 {-\r\n(.*?)\s\s}을 사용하고 있습니다. 여기서 중괄호는 모든 변수 대체를 방지합니다. 출력물에는 두 번째 행에 하이픈이 가득 찼습니다. 그럼 줄 바꿈. 그런 다음 3 번째 줄 내용. 사용 된 정규 표현식을 디코딩합시다.

-\r\n은 하나의 리터럴 하이픈과 새 라인을 일치시키는 것입니다. 그러면 두 번째 줄의 마지막 하이픈과 줄 바꿈이 이제는 세 번째 줄과 일치합니다. 따라서 \s\s에 일치하는 이중 공간을 만날 때까지 .*?은 필수 출력 (예 : abcd 12)과 일치합니다.

왜 내가 하위 일치 패턴을 얻는 데 사용되는 괄호가 필요한지 궁금 할 것입니다.

일반적으로 expect은 예상 전체 일치 문자열을 expect_out(0,string)에 저장하고 모든 일치/일치하지 않는 입력을 expect_out(buffer)에 버퍼링합니다.각 하위 일치는 expect_out(1,string), expect_out(2,string) 등과 같이 문자열의 후속 번호 매기기에 저장됩니다. DONAL는 지적 덜 지저분한 외모 때문에

enter image description here

, 작은 따옴표의 접근 방식을 사용하는 것이 좋습니다. :)

큰 따옴표가있는 경우 \r을 백 슬래시로 이스케이프하지 않아도됩니다.

업데이트 : -\r\n(.*?)\s\s-\r\n(\w+\s+\w+)\s\s에서 regexp을 변경 한

. 귀하의 요구 사항 - - 이런 식으로

같은 match any number of letters and single spaces until you encounter first occurrence of double spaces in the output 이제

로의 귀하의 질문에 올 수 있습니다. 시도해 보았습니다. -\r\n(\w+)\s\s. 그러나 \w+에 문제가 있습니다. \w+은 공백 문자와 일치하지 않음을 기억하십시오. 출력물에 공백이 두 칸있을 때까지 공백이 있습니다.

regexp의 사용은 일치시킬 입력 문자열에 대한 요구 사항에 따라 달라집니다. 필요에 따라 정규 표현식을 사용자 정의 할 수 있습니다.

업데이트 버전 2 : .*?의 의미는 무엇

. 따로 묻는다면, 나는 당신이 논평 한 것을 반복 할 것입니다. 정규 표현식에서 *은 욕심 많은 연산자이고 ?은 우리의 생명을 구하는 사람입니다. 우리가 지금

Stackoverflow is already overflowing with number of users. 

와 같은 문자열을 고려 정규 표현식 아래 .*flow의 효과를 보자.

*

enter image description here

는 문자의 번호와 일치합니다. 좀 더 정확히 말하자면 패턴 자체가 일치하면서 가능한 한 가장 긴 문자열을 찾습니다. 따라서이 패턴의 및 flow과 일치하는 패턴의 .*은 문자열의 flow과 일치하는 패턴입니다.

이제는 .*이 문자열 flow의 첫 번째 발생과 일치하지 않게하기 위해 을 추가합니다. ?이 추가됩니다. 패턴이 비 탐욕적인 방식으로 행동하는 데 도움이됩니다.

enter image description here

지금, 다시 질문으로 돌아 오는. .*\s\s을 사용했다면 가능한 한 많이 일치하려고하므로 전체 줄과 일치합니다. 이것은 정규식의 일반적인 동작입니다.

업데이트 버전 3 :

는 다음과 같은 방법으로 당신의 코드가 있습니다.흐름이 제대로 일어난 경우

x=$(expect -c " 
spawn ssh [email protected] 
expect \"password\" 
send \"password\r\" 
expect {\\\$} { puts matched_literal_dollar_sign} 
send \"cat input\r\" 
expect -re {-\r\n(.*?)\s\s} 
if {![info exists expect_out(1,string)]} { 
     puts \"Match did not happen :(\" 
     exit 1 
} 
set output \$expect_out(1,string) 
#puts \$expect_out(1,string) 
puts \"Result : \$output\" 
") 
y=$? 

# $x now contains the output from the 'expect' command, and $y contains the 
# exit status 
echo $x 
echo $y; 

, 다음 종료 코드는 그렇지 0으로 값을가집니다, 그것은이 방법 1.이있을 것이다, 당신은 bash는 스크립트에서 반환 값을 확인할 수 있습니다.

info exists 명령에 대해 알아 보려면 here을보십시오.

+0

'$'를 역 슬래스 (-)해야합니다. 그렇지 않으면 유닉스 쉘이 그것을 조작합니다. 'expect -c "를 사용하면 ..."단지 모든 것을 성가신 엉망으로 만든다. '\ r'는 추가 백 슬래쉬가 필요할 수도 있습니다. –

+0

@linux_newbie : 답변을 업데이트했습니다. 확인해주십시오. – Dinesh

+0

@DonalFellows :이 점에 대해 더 자세히 알기 위해 나를 도와 준 Donalan에게 정말 감사드립니다. 나는 나의 대답을 시험 할뿐만 아니라 교정했다. 다른 변경 사항에 대해 알려주십시오. – Dinesh

관련 문제