Bash

使用儲存在 shell 變數中的行號列印行,使用 sed

  • April 27, 2021

我有一個選項卡文件,我從中提取包含行號的列,我需要從另一個文件中提取行。我得到了行號,cut -f並將它們儲存到一個變數list中。我嘗試使用sed以下內容:

$ list="2 5 7 10"
$ echo $list
2 5 7 10
$ sed -n "$list p" longText.txt 
sed: -e expression #1, char 3: unknown command: `5'
$ sed -n "${list}p" longText.txt 
sed: -e expression #1, char 3: unknown command: `5'

錯誤是什麼?什麼是正確的語法?

sed只需在您的命令之前放置一個 echo即可查看您出錯的原因。

使用sed編輯器的一種方法是:

# assuming default IFS
## based on Kusalananda's observations
set -f ;# disable globbing
list="2 5 7 10"
for i in $list;do
 echo "${i}p"
done | sed -nf - longText.txt

## or per Kusalanda method has a bug in it
## for empty list it generates wrong output
# printf '%sp\n' $list | sed -nf - lonxt.txt

您的程式碼的問題是您嘗試執行類似的sed命令

2 5 7 10p

這顯然是沒有意義的sed,所以它抱怨。

您的部分問題是使用單個字元串來保存許多不同的項目(行號)。最好使用數組來完成。然後,每個數組元素(行號)都需要在其後p插入一個單獨的sed命令。

對於數字 2、5、7 和 10,您需要一個sed類似於

2p; 5p; 7p; 10p;

或者

2p;5p;7p;10p;

或者

2p
5p
7p
10p

您可以從以下數組中輕鬆創建這樣的腳本bash

lines=( 2 5 7 10 )
printf '%sp\n' "${lines[@]:-"q;"}" | sed -n -f /dev/stdin longText.txt

這用於從數字列表中printf創建一個sed腳本,並將其提供給sed從標準輸入中讀取的腳本-f /dev/stdin,並將其應用於您的文件。

如果列表為空,printf則將發出一個sed不做任何事情的表達式,然後終止sed


如果您需要在字元串中使用數字,則可以將該字元串轉換為有效sed腳本並將其應用到您的文件中,如下所示:

sed 's/[[:digit:]]\{1,\}/&p;/g' <<<"$list" | sed -n -f /dev/stdin longText.txt

給定 string 2 5 7 10,這將生成sed腳本2p; 5p; 7p; 10p;,然後以與上述類似的方式將其應用於您的文件。

空列表不會導致sed輸出任何內容。

引用自:https://unix.stackexchange.com/questions/646741