在Go語言開發中,有時候我們可能會遇到從”HijackedResponse”中刪除光標位置的ANSI轉義代碼的需求。這些轉義代碼通常用于在終端上展示彩色文本或者控制光標位置,但是在某些情況下,我們可能需要將其刪除。本文將介紹如何通過使用Go語言的字符串操作函數以及正則表達式,從”HijackedResponse”中刪除這些ANSI轉義代碼。無論您是Go語言初學者還是有一定經驗的開發者,本文都將幫助您解決這一問題。
問題內容
我正在嘗試使用 go 執行(交互)一個 docker 容器。
這是我正在使用的代碼:
func (docker *docker) redirectresponsetooutputstream(outputstream, errorstream io.writer, resp io.reader) error {
_, err := stdcopy.stdcopy(outputstream, errorstream, resp)
return err
}
func (docker *docker) holdhijackedconnection(inputstream io.reader, outputstream, errorstream io.writer, resp types.hijackedresponse) error {
receivestdout := make(chan error)
if outputstream != nil || errorstream != nil {
go func() {
receivestdout <- docker.redirectresponsetooutputstream(outputstream, errorstream, resp.reader)
}()
}
stdindone := make(chan struct{})
go func() {
if inputstream != nil {
io.copy(resp.conn, inputstream)
}
resp.closewrite()
close(stdindone)
}()
select {
case err := <-receivestdout:
return err
case <-stdindone:
if outputstream != nil || errorstream != nil {
return <-receivestdout
}
}
return nil
}
登錄后復制
…并在此處調用 holdhijackedconnection:
func (docker *Docker) ContainerExec(ctx context.Context, container *injection.Container) error {
createResponse, err := docker.client.ContainerExecCreate(ctx, container.ID, types.ExecConfig{
AttachStdout: true,
AttachStderr: true,
AttachStdin: true,
Detach: true,
Tty: true,
Cmd: []string{"sh"},
})
if err != nil {
return err
}
stream, err := docker.client.ContainerExecAttach(ctx, createResponse.ID, types.ExecStartCheck{})
if err != nil {
return err
}
defer stream.Close()
docker.holdHijackedConnection(os.Stdin, os.Stdout, os.Stderr, stream)
return nil
}
登錄后復制
一些注意事項:
sh 是必需的,它是高山圖像
injection.container 只是保存有關容器的信息,它是一個自定義結構體
docker 是一個結構體,用于保存 docker 客戶端(來自 github.com/docker/docker/client 的 client 的實例)
如果我執行我的應用程序,我得到的 cli 結果是這樣的:
/usr/app $ ^[[43;12r
據我所知,^[[43;12r 是光標位置的 ansi 轉義碼。
我可以執行命令,例如 ls 或 npm i 等,但我總是找回這些 ansi 轉義碼。
我的問題是,有沒有辦法從標準輸出中刪除它們?
解決方法
我最終發現了。
問題是,我應該使用 github.com/docker/cli/cli/command 包及其 dockercli 而不是 os.std...。這可以通過設置輸出、錯誤和輸入流來為我管理這個問題,如下所示:
func (docker *Docker) holdHijackedConnection(resp types.HijackedResponse) error {
cli, _ := command.NewDockerCli()
outputStream := cli.Out()
errorStream := cli.Err()
inputStream := cli.In()
inputStream.SetRawTerminal()
defer inputStream.RestoreTerminal()
receiveStdout := make(chan error)
if outputStream != nil || errorStream != nil {
go func() {
receiveStdout <- docker.redirectResponseToOutputStream(outputStream, errorStream, resp.Reader)
}()
}
stdinDone := make(chan struct{})
go func() {
if inputStream != nil {
io.Copy(resp.Conn, inputStream)
}
resp.CloseWrite()
close(stdinDone)
}()
select {
case err := <-receiveStdout:
return err
case <-stdinDone:
if outputStream != nil || errorStream != nil {
return <-receiveStdout
}
}
return nil
}
登錄后復制
如果要添加ctrl+c轉義,需要在containerexeccreate處的execconfig中設置detachkeys。否則執行 exit 將分離它。






