Bash 기능이 라인을 올바르게 실행하고 싶지 않은 것 같습니다.

Bash 기능이 라인을 올바르게 실행하고 싶지 않은 것 같습니다.

이 질문은 무의미하지만 시작해 보겠습니다! 저는 bash에서 IRC 클라이언트를 개발 중인데 일부 코드를 발견하여 제가 개발 중인 IRC bash 봇 코드에 추가하기 시작했습니다. 단순화하기 위해 분해해봤습니다. GNU bash, 버전 4.3.48(1) - 출시됨

#!/bin/bash
#!/user/bin/perl

function status_line() {
    echo -en '\e7' "\e[${status_line_row};0f" '\e[2K'
    echo -en "\e[4;44mSTATUS: $nick in $channel @ $channel\e[0m"
    echo -en '\e8'
}

function read_line() {
while true
do
    while read -r -t1
    do 
        status_line
        echo -en '\e[2K\r> '
        echo "PRIVMSG $channel :$REPLY" >> $input   
    done
done
}

. bot.properties
input=".bot.cfg"
echo "Starting session: $(date "+[%y:%m:%d %T]")">$log 
echo "NICK $nick" > $input 
echo "USER $user" >> $input
echo "JOIN $channel" >> $input

read_line | tail -f $input | openssl s_client -connect $server:6697 

이 명령을 실행하고 터미널에 입력을 입력한 후 올바르게 입력하고 $REPLY를 IRC로 보내지만 read_line 내에서 status_line 및 echo -en '\e[2K\r> '를 올바르게 실행하지 못합니다. 입력을 읽는 이유가 혼란 스럽지만 입력 전 두 줄이 작동하지 않습니다. IRC에 메시지를 보낸 후 이를 확인하기 위해 bash -x를 실행했지만(아래) -x 없이는 문제가 해결되지 않았습니다.

+ status_line
+ echo -en '\e7' '\e[;0f' '\e[2K'
+ echo -en '\e[4;44mSTATUS: Omen in #lair @ #lair\e[0m'
+ echo -en '\e8'
+ echo -en '\e[2K\r> '
+ read -r -t1
+ true

전체 코드를 보려면 여기를 클릭하세요 >https://pastebin.com/cHLiwZNf

답변1

function read_line() {
    ...
    while read -r -t1; do
        status_line
        echo -en '\e[2K\r> '
        echo "PRIVMSG $channel :$REPLY" >> $input   
    ...
}

read_line | tail ...

read_line에서 status_line 및 echo -en '\e[2K\r> '를 올바르게 수행하지 못합니다. 입력을 읽는 이유가 혼란 스럽지만 입력 전 두 줄이 작동하지 않습니다.

내부적으로 를 read_line사용하여 표준 입력에서 읽은 다음 를 사용 read하여 표준 출력으로 인쇄할 수 있습니다 echo. ( $input다른 에서도 작동 echo하지만 문제가 되지 않습니다.)

read_line파이프라인의 일부로 함수를 어떻게 호출하는지 확인하고 read_linestdin과 stdout이 연결된 위치를 생각해 보세요. 파이프는 관련된 명령의 입력 및 출력 스트림에 대해 무엇을 합니까? tail표준입력에 어떤 역할을 합니까?


또한 이것이 >사용자에게 프롬프트가 되어야 한다면 아마도 인쇄되어야 한다는 점에 유의하십시오.앞으로이후가 아닌 에 전화하세요 read. 이를 실행하거나 while echo -en '\e[2K\r> '; read -r -t1; do ...이를 사용하여 read -p프롬프트를 인쇄하도록 하십시오. 터미널이 일반적인 방식으로 설정된 경우 사용자가 Enter 키를 누를 때나 read무언가가 인쇄될 때 화면이 스크롤됩니다. 상태 표시줄이 화면 상단에 있으면 스크롤되어 보이지 않게 됩니다. 이에 대해 뭔가 조치를 취해야 하며 ncurses기존 UI 라이브러리를 사용하는 것이 훨씬 쉽습니다(예: 셸에서 터미널 처리를 수동으로 수정).

IRC 클라이언트의 또 다른 문제는필요동시에 두 곳에서 읽을 수 있습니다: 사용자의 입력과 네트워크의 데이터. 처리를 위해 출력을 openssl다시 스크립트로 수정하는 것은 그 자체로 약간 어색하며 동시에 두 가지를 모두 읽어야 하는 것은 더 나쁩니다.

실제 해결책은 다음을 사용하는 것입니다.시스템 select()호출(또는 poll()). Bash는 /dev/tcp의사 파일을 통해 네트워크 소켓에 대한 액세스를 제공하지만 select().

따라서 실제로 사용하는 두 가지 중요한 이유가 있습니다.실제 프로그래밍 언어그리고껍질이 아니다이를 위해.

물론, 그냥 미친 연습으로 이 작업을 수행하는 경우에는 괜찮지만, 그렇다면 이와 같은 문제를 해결하기 전에 쉘 언어에 조금 익숙해지는 것이 좋습니다. 또한, 실제적인 영향 없이 제한된 환경에서 프로그래밍을 즐기고 싶다면 다음 중 몇 가지를 추천해 드릴 수 있습니다.자크 전자 공사그런 이유로.

답변2

@Kusalananda 덕분에 그들의 답변을 통해 검색을 하게 되었고 답변을 찾았습니다. 그들이 준 답변이 맞다면 다시 한 번 감사드립니다. 죄송합니다. 하하! 어쨌든, >&2터미널에 인쇄하고 싶은 줄 끝에 추가하세요! 아직도 그것을 사용하고 내 상황에 적응하고 있지만 효과가 있습니다!

function read_line() {
while true
do
    while read -r -t1 REPLY
    do 
        echo 'Hello World' >&2
        echo -en '\e[2K\r> ' >&2
        echo "PRIVMSG $channel :$REPLY" >> $input   
    done
done
}

답변3

첫째, 여기서 풀어야 할 내용이 많습니다. 아직 사용을 시작하지 않으셨다면주택 검사, 그런 다음 시작해야 합니다. 글을 쓰는 동안 결함을 강조하여 삶을 더 쉽게 만듭니다.

둘째, 쉘은 다음 줄을 좋아하지 않습니다: echo -en '\e7' "\e[${status_line_row};0f" '\e[2K'. 무엇을 해야 할지 잘 모르겠지만 커서가 한 줄 위로 올라가서 원하는 내용이 아닐 것 같은 공백(?)을 쓰게 됩니다. 먼저 이 문제를 해결하세요.

다음으로, 이 블록의 맥락에서 비트 while true는 필요하지 않은 것처럼 보입니다.

function read_line() {
while true; do <- unnecessary
    while read -r -t1
    do 
        status_line
        echo -en '\e[2K\r> '
        echo "PRIVMSG $channel :$REPLY" >> $input   
    done
done <- unnecessary
}

# This should do exactly the same thing but you have to feed the loop
while read -r -t1; do 
    status_line
    echo -en '\e[2K\r> '
    echo "PRIVMSG $channel :$REPLY" >> $input   
done < /from/file, or
done <<< "$fromVariable" (pick one from file or variable)

마지막으로 여기에요점이는 출력을 보다 쉽게 ​​색상화하는 방법을 간략하게 설명하는 데 도움이 됩니다. 나는 그것을 라이브러리라고 부르고 여러 스크립트에서 재사용합니다. 추신: 이 솔루션은 마음에 들지 않지만 작동합니다.

관련 정보