Скажем, у меня есть файл с именем before.txt
, который читает:
1
2
3
4
, но я хочу заменить число 4
числом (в order) из текстового файла с именем after.txt
. Как мне это сделать?
after.txt
содержит:
2743
3028
2850
1092
etc.
Можно ли это также превратить в скрипт? Если это так, я бы хотел, чтобы он перебрал все строки из after.txt
по порядку и заменил строку 4
, как сказано выше.
Учитывая эти файлы:
cat before.txt
1
2
3
4
1
1
2
3
4
2
3
4
cat after.txt
2743
3028
2850
1092
И этот маленький скрипт:
#!/bin/bash
while read -r line; do
if [[ "$line" == 4 ]]; then
sed -n '1p' after.txt
sed -i".bup" '1d' after.txt
else
echo "$line"
fi
done < before.txt
Я получаю такой результат:
./script.sh
1
2
3
2743
1
1
2
3
3028
2
3
2850
Я уверен, что есть awk
oneliner, который может сделать это, но я не говорю awk
свободно! Также, если вы хотите заменить ("на место") файл before.txt
, вам придется изменить операторы sed
в цикле. В противном случае вы можете просто перенаправить STDOUT
в новый файл. В этом примере я решил вывести все в STDOUT
для удобства просмотра.
Проверено под OS X 10.11.6 и BSD sed
Что-то вроде этого в awk?
$ awk 'NR==FNR{Arr[NR]=$0;next}{if($0==4){i++;print Arr[i]}else{print}}' after.txt before.txt
1
2
3
2743
1
1
2
3
3028
2
3
2850
awk '/^4$/&&getline<"after.txt"||1' before.txt
Если текущая запись $ 0
- это в точности текст 4
, тогда получить следующую строку из after.txt
. Если это успешно, оно становится $ 0
, а getline
возвращает 1, поэтому выражение истинно и запускается действие по умолчанию {print}
.
Если запись не 4
, или getline возвращает 0
в EOF
из after.txt
, || 1
гарантирует, что мы по-прежнему печатаем текущую запись. $ 0
не изменяется, если чтение after.txt
не удается.
Если getline
завершается ошибкой с -1
, мы все равно печатаем $ 0
, поскольку это ненулевой код возврата.