Shell:在匹配模式的每一行末尾添加字符串。文件名在另一个文件中给出
Shell: Add string to the end of each line, which match the pattern. Filenames are given in another file
我还是 shell 的新手,需要一些帮助。
- 我有一个文件
stapel_old
。
- 我在同一目录中还有
english_old_sync
、math_old_sync
和 vocabulary_old_sync
等文件。
stapel_old
的内容是:
english
math
vocabulary
例如的内容英语是:
basic_grammar.md
spelling.md
orthography.md
我想操作 stapel_old 中给出的所有文件,如本例所示:
- 取
stapel_old
的第一行'english',(之后是数学,依此类推)
- 在这种情况下将英语转换为 english_old_sync,(或者之后将第二行给出的内容转换为 math_old_sync)
- 在
english_old_sync
中逐行搜索模式“.md
”
- 并追加到.md之后的每一行
:::#a1
结果应该是例如的 english_old_sync:
basic_grammar.md:::#a1
spelling.md:::#a1
orthography.md:::#a1
共math_old_sync:
geometry.md:::#a1
fractions.md:::#a1
等等。 stapel_old
应该保持不变。
我怎样才能意识到这一点?
我尝试使用 sed -n,while 循环(while read -r 行),我觉得它在某种程度上是正确的方式 - 但在检查和阅读 4 小时后我仍然遇到错误,而不是预期的结果。
谢谢!
编辑
这是工作代码(文件存储在文件夹 'olddata' 中):
clear
echo -e "$(tput setaf 1)$(tput setab 7)Learning directories:$(tput sgr 0)\n"
# put here directories which should not become flashcards, command: | grep -v 'name_of_directory_which_not_to_learn1' | grep -v 'directory2'
ls ../ | grep -v 00_gliederungsverweise | grep -v 0_weiter | grep -v bibliothek | grep -v notizen | grep -v Obsidian | grep -v z_nicht_uni | tee olddata/stapel_old
# count folders
echo -ne "\nHow much different folders: " && wc -l olddata/stapel_old | cut -d' ' -f1 | tee -a olddata/stapel_old
echo -e "Are this learning directories correct? [j ODER y]--> yes; [Other]-->no\n"
read lernvz_korrekt
if [ "$lernvz_korrekt" = j ] || [ "$lernvz_korrekt" = y ];
then
read -n 1 -s -r -p "Learning directories correct. Press any key to continue..."
else
read -n 1 -s -r -p "Learning directories not correct, please change in line 4. Press any key to continue..."
exit
fi
echo -e "\n_____________________________\n$(tput setaf 6)$(tput setab 5)Found cards:$(tput sgr 0)$(tput setaf 6)\n"
#GET && WRITE FOLDER NAMES into olddata/stapel_old
anzahl_zeilen=$(cat olddata/stapel_old |& tail -1)
#GET NAMES of .md files of every stapel and write All to 'stapelname'_old_sync
i=0
name="var_$i"
for (( num=1; num <= $anzahl_zeilen; num++ ))
do
i="$((i + 1))"
name="var_$i"
name=$(cat olddata/stapel_old | sed -n "$num"p)
find ../$name/ -name '*.md' | grep -v trash | grep -v Obsidian | rev | cut -d'/' -f1 | rev | tee olddata/$name"_old_sync"
done
(tput sgr 0)
我尝试添加:
input="olddata/stapel_old"
while IFS= read -r line
do
sed -n "$line"p olddata/stapel_old
done < "$input"
仅更改 english_old_sync 的代码是:
lines=$(wc -l olddata/english_old_sync | cut -d' ' -f1)
for ((num=1; num <= $lines; num++))
do
content=$(sed -n "$num"p olddata/english_old_sync)
sed -i "s/"$content"/""$content":::#a1/g"" olddata/english_old_sync
done
所以现在,这需要是一个内部 for 循环,一个包含英语变量的外部 for 循环,对吗?
stapel_old should stay unchanged.
您可以尝试 while
+ read
循环并将 sed
嵌入循环中。
#!/usr/bin/env bash
while IFS= read -r files; do
echo cp -v "$files" "${files}_old_sync" &&
echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old
convert in this case english to english_old_sync, (or after that what is given in second line, e.g. math to math_old_sync)
cp
用新名称复制文件,如果目标是从文件内容重命名原始文件名 staple_old
然后更改 cp
至 mv
sed
中的 -n
和 -i
标记已被省略,如果需要,请包含它。
该脚本还假定 staple_old
文件的内容中没有 empty/blank 行。如果万一 are/is 在 do
所在的行之后添加一个附加测试。
[[ -n $files ]] || continue
它还假定staple_old
的内容是现有文件。以防万一添加额外的测试。
[[ -e $files ]] || { printf >&2 '%s no such file or directory.\n' "$files"; continue; }
或 if
语句。
if [[ ! -e $files ]]; then
printf >&2 '%s no such file or directory\n' "$files"
continue
fi
另见 help test
另见 help continue
将它们组合在一起应该是这样的:
#!/usr/bin/env bash
while IFS= read -r files; do
[[ -n $files ]] || continue
[[ -e $files ]] || {
printf >&2 '%s no such file or directory.\n' "$files"
continue
}
echo cp -v "$files" "${files}_old_sync" &&
echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old
- 删除
echo
如果您对输出感到满意,那么脚本可以 copy/rename 并编辑文件。
我还是 shell 的新手,需要一些帮助。
- 我有一个文件
stapel_old
。 - 我在同一目录中还有
english_old_sync
、math_old_sync
和vocabulary_old_sync
等文件。
stapel_old
的内容是:
english
math
vocabulary
例如的内容英语是:
basic_grammar.md
spelling.md
orthography.md
我想操作 stapel_old 中给出的所有文件,如本例所示:
- 取
stapel_old
的第一行'english',(之后是数学,依此类推) - 在这种情况下将英语转换为 english_old_sync,(或者之后将第二行给出的内容转换为 math_old_sync)
- 在
english_old_sync
中逐行搜索模式“.md
” - 并追加到.md之后的每一行
:::#a1
结果应该是例如的 english_old_sync:
basic_grammar.md:::#a1
spelling.md:::#a1
orthography.md:::#a1
共math_old_sync:
geometry.md:::#a1
fractions.md:::#a1
等等。 stapel_old
应该保持不变。
我怎样才能意识到这一点?
我尝试使用 sed -n,while 循环(while read -r 行),我觉得它在某种程度上是正确的方式 - 但在检查和阅读 4 小时后我仍然遇到错误,而不是预期的结果。
谢谢!
编辑
这是工作代码(文件存储在文件夹 'olddata' 中):
clear
echo -e "$(tput setaf 1)$(tput setab 7)Learning directories:$(tput sgr 0)\n"
# put here directories which should not become flashcards, command: | grep -v 'name_of_directory_which_not_to_learn1' | grep -v 'directory2'
ls ../ | grep -v 00_gliederungsverweise | grep -v 0_weiter | grep -v bibliothek | grep -v notizen | grep -v Obsidian | grep -v z_nicht_uni | tee olddata/stapel_old
# count folders
echo -ne "\nHow much different folders: " && wc -l olddata/stapel_old | cut -d' ' -f1 | tee -a olddata/stapel_old
echo -e "Are this learning directories correct? [j ODER y]--> yes; [Other]-->no\n"
read lernvz_korrekt
if [ "$lernvz_korrekt" = j ] || [ "$lernvz_korrekt" = y ];
then
read -n 1 -s -r -p "Learning directories correct. Press any key to continue..."
else
read -n 1 -s -r -p "Learning directories not correct, please change in line 4. Press any key to continue..."
exit
fi
echo -e "\n_____________________________\n$(tput setaf 6)$(tput setab 5)Found cards:$(tput sgr 0)$(tput setaf 6)\n"
#GET && WRITE FOLDER NAMES into olddata/stapel_old
anzahl_zeilen=$(cat olddata/stapel_old |& tail -1)
#GET NAMES of .md files of every stapel and write All to 'stapelname'_old_sync
i=0
name="var_$i"
for (( num=1; num <= $anzahl_zeilen; num++ ))
do
i="$((i + 1))"
name="var_$i"
name=$(cat olddata/stapel_old | sed -n "$num"p)
find ../$name/ -name '*.md' | grep -v trash | grep -v Obsidian | rev | cut -d'/' -f1 | rev | tee olddata/$name"_old_sync"
done
(tput sgr 0)
我尝试添加:
input="olddata/stapel_old"
while IFS= read -r line
do
sed -n "$line"p olddata/stapel_old
done < "$input"
仅更改 english_old_sync 的代码是:
lines=$(wc -l olddata/english_old_sync | cut -d' ' -f1)
for ((num=1; num <= $lines; num++))
do
content=$(sed -n "$num"p olddata/english_old_sync)
sed -i "s/"$content"/""$content":::#a1/g"" olddata/english_old_sync
done
所以现在,这需要是一个内部 for 循环,一个包含英语变量的外部 for 循环,对吗?
stapel_old should stay unchanged.
您可以尝试 while
+ read
循环并将 sed
嵌入循环中。
#!/usr/bin/env bash
while IFS= read -r files; do
echo cp -v "$files" "${files}_old_sync" &&
echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old
convert in this case english to english_old_sync, (or after that what is given in second line, e.g. math to math_old_sync)
cp
用新名称复制文件,如果目标是从文件内容重命名原始文件名staple_old
然后更改cp
至mv
sed
中的-n
和-i
标记已被省略,如果需要,请包含它。该脚本还假定
staple_old
文件的内容中没有 empty/blank 行。如果万一 are/is 在do
所在的行之后添加一个附加测试。[[ -n $files ]] || continue
它还假定
staple_old
的内容是现有文件。以防万一添加额外的测试。[[ -e $files ]] || { printf >&2 '%s no such file or directory.\n' "$files"; continue; }
或 if
语句。
if [[ ! -e $files ]]; then
printf >&2 '%s no such file or directory\n' "$files"
continue
fi
另见
help test
另见
help continue
将它们组合在一起应该是这样的:
#!/usr/bin/env bash
while IFS= read -r files; do
[[ -n $files ]] || continue
[[ -e $files ]] || {
printf >&2 '%s no such file or directory.\n' "$files"
continue
}
echo cp -v "$files" "${files}_old_sync" &&
echo sed '/^.*\.md$/s/$/:::#a1/' "${files}_old_sync"
done < olddata/staple_old
- 删除
echo
如果您对输出感到满意,那么脚本可以 copy/rename 并编辑文件。