#bash #shell #awk #sed #echo
Вопрос:
у меня есть файл с некоторым содержимым, и мне нужно повторить n-й раз и добавить приращение номера последнего столбца.
Input content of a file:
TCTA 7 ccta TCTA 1
TCTA 8 ccta TCTA 1
TCTA 9 ccta TCTA 1
TCTA 10 ccta TCTA 1
TCTA 11 ccta TCTA 1
TCTA 12 ccta TCTA 1
TCTA 13 ccta TCTA 1
TCTA 14 ccta TCTA 1
TCTA 15 ccta TCTA 1
TCTA 16 ccta TCTA 1
TCTA 17 ccta TCTA 1
Expected output:
TCTA 7 ccta TCTA 1
TCTA 8 ccta TCTA 1
TCTA 9 ccta TCTA 1
TCTA 10 ccta TCTA 1
TCTA 11 ccta TCTA 1
TCTA 12 ccta TCTA 1
TCTA 13 ccta TCTA 1
TCTA 14 ccta TCTA 1
TCTA 15 ccta TCTA 1
TCTA 16 ccta TCTA 1
TCTA 17 ccta TCTA 1
TCTA 7 ccta TCTA 2
TCTA 8 ccta TCTA 2
TCTA 9 ccta TCTA 2
TCTA 10 ccta TCTA 2
TCTA 11 ccta TCTA 2
TCTA 12 ccta TCTA 2
TCTA 13 ccta TCTA 2
TCTA 14 ccta TCTA 2
TCTA 15 ccta TCTA 2
TCTA 16 ccta TCTA 2
TCTA 17 ccta TCTA 2
TCTA 7 ccta TCTA 3
TCTA 8 ccta TCTA 3
TCTA 9 ccta TCTA 3
TCTA 10 ccta TCTA 3
TCTA 11 ccta TCTA 3
TCTA 12 ccta TCTA 3
TCTA 13 ccta TCTA 3
TCTA 14 ccta TCTA 3
TCTA 15 ccta TCTA 3
TCTA 16 ccta TCTA 3
TCTA 17 ccta TCTA 3
TCTA 7 ccta TCTA n
TCTA 8 ccta TCTA n
TCTA 9 ccta TCTA n
TCTA 10 ccta TCTA n
TCTA 11 ccta TCTA n
TCTA 12 ccta TCTA n
TCTA 13 ccta TCTA n
TCTA 14 ccta TCTA n
TCTA 15 ccta TCTA n
TCTA 16 ccta TCTA n
TCTA 17 ccta TCTA n
Я попытался следовать, но не смог увеличить последний столбец в n-й раз.
for i in {1..5};do
cat file.txt >> out.txt
done
Мне нужно, чтобы последняя колонка увеличилась в n-й раз.
Комментарии:
1. Гарантируется ли, что входной файл будет иметь тот же номер в последнем столбце? Гарантировано ли, что это число будет единицей? Если число отличается, следует ли повторять строки только до тех пор, пока конечное число не будет увеличено до указанного максимального значения (т. Е. Должны ли некоторые строки появляться в выводе больше раз, чем другие)?
2. На каждой итерации вы должны заменить последнее число в строке текущим порядковым номером. Поэтому вы не можете использовать cat. Вместо этого вы должны — внутри каждой итерации
i
— писать явный цикл по строкам входного файла и для каждой строки корректировать последнее поле строки.
Ответ №1:
Использование решения gnu-awk:
awk -v n=3 '
{
rec = rec $0 RS
}
1
END {
for (i=2; i<=n; i)
printf "%s", gensub(/[0-9] (n|$)/, i "\1", "g", rec)
}' file
TCTA 7 ccta TCTA 1
TCTA 8 ccta TCTA 1
TCTA 9 ccta TCTA 1
TCTA 10 ccta TCTA 1
TCTA 11 ccta TCTA 1
TCTA 12 ccta TCTA 1
TCTA 13 ccta TCTA 1
TCTA 14 ccta TCTA 1
TCTA 15 ccta TCTA 1
TCTA 16 ccta TCTA 1
TCTA 17 ccta TCTA 1
TCTA 7 ccta TCTA 2
TCTA 8 ccta TCTA 2
TCTA 9 ccta TCTA 2
TCTA 10 ccta TCTA 2
TCTA 11 ccta TCTA 2
TCTA 12 ccta TCTA 2
TCTA 13 ccta TCTA 2
TCTA 14 ccta TCTA 2
TCTA 15 ccta TCTA 2
TCTA 16 ccta TCTA 2
TCTA 17 ccta TCTA 2
TCTA 7 ccta TCTA 3
TCTA 8 ccta TCTA 3
TCTA 9 ccta TCTA 3
TCTA 10 ccta TCTA 3
TCTA 11 ccta TCTA 3
TCTA 12 ccta TCTA 3
TCTA 13 ccta TCTA 3
TCTA 14 ccta TCTA 3
TCTA 15 ccta TCTA 3
TCTA 16 ccta TCTA 3
TCTA 17 ccta TCTA 3
Комментарии:
1. Привет, Анубхав, Спасибо, что он работает (мне нужно установить; «заварить, установить gawk» и использовал gawk вместо awk только). Более того, я никогда не использовал функцию gensub, не могли бы вы объяснить все, как ваши команды объясняют ситуацию ? Спасибо
2.
gensub
использует регулярное[0-9] (n|$)
выражение для поиска в строкеrec
. Который в основном является последним числом в каждой строке и заменяет его тем,i
которое повторяется от2
доn
.(n|$)
это группа захвата для захвата каждого разрыва строки или конца строки, и вместо этого мы просто возвращаем ее обратно послеi
использования обратной ссылки\1
."g"
предназначен для глобальной замены.3.Эй, Анубхав, Спасибо, вы можете мне помочь, если я хочу продлить для второго последнего столбца, а также для последнего столбца при изменении ввода?
TCTA 3 TCTG 1 TCTA 1
TCTA 4 TCTG 1 TCTA 1
4. @SandeepKumar Очень трудно понять требование из раздела комментариев. Будет намного лучше, если вы создадите новый вопрос, и вы получите лучшую помощь.
Ответ №2:
Это может сработать для вас (GNU parallel и sed):
parallel -kq sed -E 's/S $/$((amp; {}))/;s/.*/echo "amp;"/e' file ::: {0..2}
Если вы хотите заменить последнее поле на приращение, используйте:
parallel -kq sed -E 's/S $/{}/' file ::: {1..3}