Bash

如果在輔助列表中找到匹配項,則替換主列表中的欄位

  • January 12, 2021

我有一個包含大約幾千行的列表,每行包含 4 或 5 個欄位。我還有第二個列表,包含幾行,只有 1 個欄位。兩個列表都將儲存在一個變數中。

第一個列表:

item_1 something something value something
item_2 something something value 
item_3 something something value something
item_4 something something value something
... 
item_2155 something something value 
item_2156 something something value something

第二名單:

item_3
item_2155

期望的最終結果:

item_1 something something value something
item_2 something something value 
item_3 something something new_value something
item_4 something something value something
...
item_2155 something something new_value 
item_2156 something something value something

我嘗試在 while 循環中使用 sed。它有點工作,但是這種方法在每次循環時都會將列表附加到自身。我也覺得 awk 可能是一個更好的解決方案。

#!/bin/bash

MYHUGELIST=$(command)
MYSHORTLIST=$(command)

while read -r line ; do
 sed "/^$line /s/1of3-possible-matches/newvalue/;/^$line /s/2of3-possible-matches/newvalue/;/^$line /s/3of3-possible-matches/newvalue/" <<< "$MYHUGELIST"
done <<< "$MYSHORTLIST"

您會考慮使用awk而不是解決方案sed嗎?如果是,

#!/bin/bash

read -r -d '' shortlistOneString < shortlist.txt

awk -v oldv=value -v newv=new_value -v s="$shortlistOneString" \
'BEGIN {n=split(s,a,"\n")} { \
found=0; \
for (i=1; ! found && i<=n; ++i) { \
 if (a[i] == $1) { \
   for (j=2; j<= NF; ++j) { \
     if ($j == oldv) { \
       $j = newv; found=1; break }}}}; \
print}' longlist.txt

筆記

  • 我們將整個shortlist.txt、換行符和所有內容讀入 shell 變數shortlistOneString
  • BEGIN塊中,我們將 的值拆分"$shortlistOneString"為我們稱為的數組a;這個數組有n元素,我們可以用 訪問第i個元素a[i]。這個塊只執行一次,在awk正確的輸入開始之前。
  • 單獨awk將每一行解析為一個特殊的保留數組;對於任何輸入行,這個數組都有NF元素,我們可以用;訪問第j個元素 $j甚至可以覆蓋這些元素。
  • 對於每一行,awk將執行第二個塊中的語句(第一個語句是found=0,最後一個語句是print)。
  • 如果第j個欄位等於oldv,我們用 覆蓋該欄位newv,然後停止查找。因為awk沒有breakBash(例如)所具有的多級,所以我們使用一個名為 的輔助變數,我們為每一行found重置它。0
  • 無論我們是否覆蓋了一個欄位,我們print每一行。
  • 此解決方案比您要求的更通用。您可以通過僅檢查每行的最後一個欄位 $(NF)和倒數第二個 欄位來收緊它$(NF-1);您甚至可以分別對欄位位置進行硬$5編碼$4

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