to add the corresponding strings in each and every file in the beginning of the file
bash+sedподход:
for f in *.md; do fn=${f##*-}; sed -i "1 s/^/${fn%.*} /" "$f"; done
fn=${f##*-}
-усекает самую длинную совпавшую последовательность слева до последнего вхождения -
(, например.abcd.md
)
${fn%.*}
-усечение самой правой последовательности (с конца )до первого вхождения.
(точки )из предыдущей подстроки fn
(, т.е.abcd
)
sed -i "1 s/^/${fn%.*} /" "$f"
-добавить нужную строку в начало файла
Вы забываете, что G
добавляется из области хранения, в которую пишет ваша первая команда, но не ваша вторая.
sed h
не удваивает каждую строку, потому что просто перезаписывает пространство хранения в каждом цикле.
Ваша первая команда эквивалентна
sed '1!G;h' <<END_INPUT
alpha
beta
gamma
END_INPUT
и выходы
alpha
beta
alpha
gamma
beta
alpha
Для всех строк, кроме первой, текущее пространство хранения добавляется к пространству шаблона с разделяющим символом новой строки. Затем он перезаписывает пространство удержания пространством шаблона. В конце каждого цикла (после обработки строки ввода )выполняется неявная командаp
(печати ).
Другой способ сказать, что «для каждой строки ввода он выводит все предыдущие строки в обратном порядке (с новой строкой последней )».
Таким образом, код будет
alpha
в пространство шаблонов, скопировать alpha
в пространство хранения, распечатать alpha
, beta
в пространство шаблонов, добавить \nalpha
в пространство шаблонов из пространства хранения, скопировать beta\nalpha
в пространство хранения, распечатать beta\nalpha
,gamma
в пространство шаблонов, добавить \nbeta\nalpha
в пространство шаблонов из пространства хранения, скопировать gamma\nbeta\nalpha
в пространство хранения, напечатать gamma\nbeta\nalpha
. Код
sed '1!G' <<END_INPUT
alpha
beta
gamma
END_INPUT
выходы
alpha
beta
gamma
(третья и последняя строки пусты ).
Этот код sed
выводит каждую строку ввода и добавляет дополнительный символ новой строки ко всем строкам, кроме первой. Он делает это потому, что
alpha
в пространство шаблонов, напечатать alpha
, beta
в пространство шаблонов, добавить \n
в пространство шаблонов из области хранения, напечатать beta\n
, gamma
в пространство шаблонов, добавить \n
к пространству шаблонов из области удержания, напечатать gamma\n
. Обратите внимание, что добавление из пространства хранения с помощью G
здесь просто добавляет дополнительную новую строку в конце пространства шаблона, поскольку оно всегда пусто (, так как вы никогда не записываете в него ).
Начнем с чего-нибудь попроще:
$ seq 4 | sed 'G;h'
1
2
1
3
2
1
4
3
2
1
Каждый блок добавляет новое число и печатает его в обратном порядке.
Почему это происходит? Давайте медленно пройдемся по процессу:
1
)(первая строка )получена sed. Эта линия помещается в пространство шаблона. G
, которая добавляет одну новую строку, за которой следует пробел к текущему пространству шаблонов. Сначала (, как и здесь ), пространство хранения пусто, поэтому sed добавляет новую строку и пустую строку (пространства хранения )к текущему пространству шаблонов. Короче говоря, он добавляет новую строку к первой строке ввода. h
. Это копирует пространство шаблона в пространство удержания. Теперь пробел содержит 1
, за которым следует новая строка. 1
, за которым следует новая строка ), потому что для sed нет опции -n
. Затем он переходит к следующей строке ввода. 2
, помещая ее в пространство шаблонов. 1
и новую строку, как указано выше, записанную в более короткой форме:1\n
)к пространству шаблонов. Теперь пространство шаблонов содержит 2\n1\n
. G
добавляет \n2\n1\n
к 3
. 3\n2\n1\n
копируется в пространство хранения с помощью h
. Все вышеперечисленное сводится к захвату строк в обратном порядке.
Этот сценарий может прояснить ситуацию. (указать место шаблона с помощьюl
):
$ seq 5 | sed -n 'G;h;l'
1\n$
2\n1\n$
3\n2\n1\n$
4\n3\n2\n1\n$
5\n4\n3\n2\n1\n$
И, как и в исходном скрипте, мы избегаем добавления новой строки в первой строке:
$ seq 5 | sed -n '1!G;h;l'
1$
2\n1$
3\n2\n1$
4\n3\n2\n1$
5\n4\n3\n2\n1$
Теперь, используя альфа, бета и гамму:
$ printf 'alpha\nbeta\ngamma' | sed -n '1!G;h;l'
alpha$
beta\nalpha$
gamma\nbeta\nalpha$
И мы возвращаемся к исходному скрипту sed:
$ printf 'alpha\nbeta\ngamma' | sed '1!G;h'
alpha
beta
alpha
gamma
beta
alpha
Что на самом деле, ИМО, должно было быть:
$ printf 'alpha\nbeta\ngamma' | sed '1!G;h;$!d'
gamma
beta
alpha
Печать только последней итерации со всеми строками в обратном порядке.
Я узнал, попробовав:
]# echo -e "a\nb\nc\nd\ne\nf" |sed '1!G;h'
a
b
a
c
b
a
d
c
b
a
e
d
c
b
a
f
e
d
c
b
a
Если читать задом наперёд :"abcdef", затем "abcde", затем "abcd", "abc", "ab", "a".
Как вы это называете?
Это работает, потому что "G" добавляет, а "h" заменяет. Если вы оставите только G;h
, вы получите дополнительные пустые строки между этими блоками.
info sed
есть пример "tac":
sed -n '1!G;$p;h'
При печати только один раз(-n
и$p
)результат будет совершенно другим :это последний "блок"sed '1!G;h'
Perl может легко имитировать этот алгоритм с (именованными )переменными:
]# echo -e "a\nb\nc" | perl -ne '$hold = $_. $hold; print $hold;'
a
b
a
c
b
a
Разворот возникает из-за того, что линия и сохраненные линии объединяются:
]# echo -e "a\nb\nc" |perl -ne '$hold.= $_; print $hold;'
a
a
b
a
b
c
$_
— входные строки. Это H=H+линия по сравнению с H=линия+H. Вы должны внимательно прочитать info sed
, чтобы найти эту и другие тонкости.