Заменить поле в первичном списке, если совпадение найдено во вторичном списке

Если вы просто хотите распечатать ссылки, все, что вам нужно, это:

echo site.com/{1..1000}

Или по одному на строку:

printf 'site.com/%s\n' {1..1000}

Если вы хотите сохранить список в виде массива:

sites=(site.com/{1..1000})
# then
for site in "${sites[@]}"...
1
11.01.2021, 02:51
3 ответа

Не могли бы вы рассмотреть решение, использующее 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, символы новой строки и все остальное в переменную оболочки shortlistOneString.
  • В блоке BEGINмы разделяем значение "$shortlistOneString"на массив, который мы назвали a; этот массив имеет nэлементов, и мы можем получить доступ к i -му элементу с помощью a[i]. Этот блок выполняется только один раз, прежде чем awkзапустится на входе.
  • Сам по себе awkанализирует каждую строку в специальный зарезервированный массив; для любой входной строки этот массив имеет NFэлементов, и мы можем получить доступ к j -му элементу с помощью $j; и может даже перезаписывать эти элементы.
  • Для каждой строки awkбудут выполняться операторы во втором блоке (, первый оператор которого — found=0, а последний —print).
  • Если j -е поле равно oldv, мы перезаписываем это поле на newvи прекращаем поиск. Поскольку awkне имеет многоуровневого -уровня break, который есть в Bash (, например ), мы обходимся вспомогательной переменной с именем found, которую мы сбрасываем на 0для каждой строки..
  • Независимо от того, перезаписали мы поле или нет, мы printкаждую строку.
  • Это решение является более общим, чем то, что вы просили.Вы можете ужесточить его, проверив только последнее поле каждой строки $(NF)и следующее -до -последнее поле$(NF-1); вы даже можете жестко закодировать позиции полей, как $5и $4соответственно.
0
18.03.2021, 22:37

Вы можете использовать sed для создания awk-скрипта

cmd1 | awk "$(cmd2 | sed -e 's:.*:/^& /{\$4=\"new_value\"}:')1"

где

  • cmd1производит$MYHUGELIST
  • cmd2производит$MYSHORTLIST
  • каждая строка в $MYSHORTLISTстановится/^item_N /{$4="new_value"}
  • финал 1в скрипте awk приводит к печати текущей строки
  • $и "символы экранируются по мере необходимости

Или, только sed -,

cmd1 | sed -e "$(cmd2 | sed -e 's:.*:/^& /s/[^ ][^ ]*/new_value/4:')"

, где флаг 4в команде sвыбирает 4-е поле.

0
18.03.2021, 22:37

Все, что вам нужно, это один простой вызов awk, никаких циклов, конвейеров или других команд не требуется.

Если ваши данные находятся в файлах:

$ awk 'NR==FNR{a[$1]; next} $1 in a{$4="new_value"} 1' secondFile firstFile
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

или если ваши данные находятся в переменных:

$ awk -v sec="$second" '
    BEGIN{split(sec,tmp); for (i in tmp) a[tmp[i]]}
    $1 in a{$4="new_value"} 1
' <<<"$first"
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
0
18.03.2021, 22:37

Теги

Похожие вопросы