Shell:在匹配模式的每一行末尾添加字符串。文件名在另一个文件中给出

Shell: Add string to the end of each line, which match the pattern. Filenames are given in another file

我还是 shell 的新手,需要一些帮助。

  1. 我有一个文件stapel_old
  2. 我在同一目录中还有 english_old_syncmath_old_syncvocabulary_old_sync 等文件。

stapel_old的内容是:

english  
math  
vocabulary

例如的内容英语是:

basic_grammar.md  
spelling.md  
orthography.md

我想操作 stapel_old 中给出的所有文件,如本例所示:

  1. stapel_old的第一行'english',(之后是数学,依此类推)
  2. 在这种情况下将英语转换为 english_old_sync,(或者之后将第二行给出的内容转换为 math_old_sync)
  3. english_old_sync 中逐行搜索模式“.md
  4. 并追加到.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 然后更改 cpmv

  • 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 并编辑文件。