簡體   English   中英

Shell腳本,轉義換行但發出其他內容?

[英]Shell script, escape newlines but emit others?

給定一個文件名,我想編寫一個shell腳本,它發出以下內容,並將其傳遞給一個進程:

Content-Length:<LEN><CR><LF>
<CR><LF>
{ "jsonrpc":"2.0", "params":{ "text":"<ESCAPED-TEXT>" } }

其中<ESCAPED-TEXT>是文件的內容,但其CR,LF和引號已被轉義為\\r\\n\\" (我猜最終也需要所有其他JSON轉義),以及<LEN>是包含轉義文本的最終JSON行的長度。

這是我目前的bash腳本解決方案。 它有效,但很難看。

(
  TXT=`cat ~/a.py | sed -E -e :a -e '$!N; s/\n/\\\n/g; ta' | sed 's/"/\\\"/g'`
  CMD='{"jsonrpc":"2.0", "params":{ "text":{"'${TXT}'"}} }'
  printf "Content-Length: ${#CMD}\r\n\r\n"
  echo -n "${CMD}"
) | pyls

有誰能建議怎么做這個更清潔,好嗎?

  • 這個sed腳本只替換LF,而不是CR。 它將每一行累積到緩沖區中,然后執行s//g以替換其中的所有LF。 我無法弄清楚在Linux和OSX / BSD上仍然有效的清潔工具。

  • 我使用了printf和echo。 第一個printf,因為我確實想發出Content-Length頭后CRLFCRLF,你顯然需要printf進行,由於回聲與逃逸行為是不統一的跨平台。 下一個回聲,因為我希望TXT中的\\r\\n文字未被轉義,printf會做什么。

上下文:有一個稱為“語言服務器協議”的標准。 基本上你運行類似的pyls我在這里運行,而且您在JsonRPC管過來標准輸入,它的管道回來的東西。 不同的人為Python(我在這里使用的pyls),C#,C ++,Typescript,PHP,OCaml,Go和Java編寫了語言服務器,每個人都傾向於在他們的語言服務器中編寫語言服務器。自己的語言。

我想編寫一個測試工具,可以將一些示例JsonRPC數據包發送到任何此類服務器。

我認為最好將我的測試工具編寫在開箱即用的所有平台上常見的基本shell腳本編寫工具中。 這樣每個人都可以使用我的測試工具來對抗他們的語言服務器。 (如果我在Python上寫它,比如說,它對我來說更容易編寫,但它會迫使C#人學習+安裝python只是為了運行它,同樣也是Typescript,PHP,OCaml,Go等鄉親。)

a.py:

print("alfa")
print("bravo")

Awk腳本:

{
  gsub("\r", "\\r")
  gsub("\42", "\\\42")
  z = z $0 "\\n"
}
END {
  printf "Content-Length: %d\r\n", length(z) + 42
  printf "\r\n"
  printf "{\42jsonrpc\42: \0422.0\42, \42params\42: {\42text\42: \42%s\42}}", z
}

結果:

Content-Length: 81

{"jsonrpc": "2.0", "params": {"text": "print(\"alfa\")\r\nprint(\"bravo\")\r\n"}}

我認為你的腳本的主要問題是沒有使用printf的格式字符串。 printf的常用方法是使用格式字符串中的各種特殊字符(如%s%b等)以及替換為格式字符串的其他參數列表。

也就是說,當你說“[我用過]回聲,因為我不希望\\ r和\\ n文字未被轉義,哪個printf會做”,問題就是不使用printf "%s" "$string"

無論如何,這里有一個想法,即如何使用這些東西在沒有外部工具的情況下完成所有操作:

escapes=('\n' '\r' '\"')         # the escapes we want to put into the output

txt=$(< ~/a.py);                 # read the file into a variable
for esc in "${escapes[@]}"; do
    # escapes are evaluated in a %b string w/ printf
    # using -v puts the result into a variable
    printf -v lit '%b' "$esc"
    # use built-in ${string//pattern/replacement} expansion
    txt=${txt//$lit/$esc}
done

txt='{"jsonrpc":"2.0", "params":{ "text":{"'$txt'"}} }'

# escapes in the format string are expanded
# but escapes in the argument substituted for %s are not
printf 'Content-Length: %s\r\n\r\n%s' "${#txt}"

“$ TXT”

有誰能建議怎么做這個更清潔,好嗎?

我想最終也需要所有其他JSON轉義

如果我已經擁有了Python,我會嘗試使用標准的Python JSON編碼器 ,至少對於字符串轉義部分。 當你可以使用已經熟悉的已知工作的東西時,為什么要將某些東西組合在一起呢?

如果我沒有Python,我喜歡Steve Penny的解決方案。 經驗法則:

  1. 要處理文件集,請使用shell
  2. 要處理文件中的數據,請使用awk
  3. 如果sed不能做到這一點,請參閱規則#2

如果你知道一點點awk,他的解決方案幾乎可以一目了然。 我會稱之為“清潔”。 如果你不懂awk,這似乎是一個很好的機會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM