【问题标题】:Writing a Bash script that takes a text file as input and pipes the text file through several commands编写一个 Bash 脚本,该脚本将文本文件作为输入并通过多个命令将文本文件传递给管道
【发布时间】:2020-07-12 18:25:45
【问题描述】:

我将带有定义的文本文件保存在一个文件夹中。我喜欢把它们转换成口语,这样我就可以听它们了。我已经通过运行一些命令手动将一些预处理代码插入到文本文件中,然后将文本转换为口语,如下所示:

sed 's/\..*$/[[slnc 2000]]/' input.txt 在第一个句点后插入一个控制码

sed 's/$/[[slnc 2000]]/' input.txt"在每行末尾插入一个控制代码

cat input.txt | say -v Alex -o input.aiff

我不想每次都重新输入这些命令,而是想创建一个 Bash 脚本,将这些命令的输出通过管道传输到最终产品。我想用脚本名称调用脚本,后跟文本文件的输入文件参数。我想保留原始文本文件,这样如果我再次打开它,实际上不会插入任何控制代码,因为控制代码的唯一目的是在音频文件中插入暂停。

我试过写

#!/bin/bash 
FILE=$1
sed 's/$/ [[slnc 2000]]/' FILE -o FILE

但是我马上就挂断了,因为它说 sed: -o: No such file or directory。有人可以帮忙吗?

【问题讨论】:

  • 使用变量时应该写$FILE。
  • 某些操作系统和sed 版本不喜欢读取和写入同一个文件。最好 (a) 在此之前加上 cat "${FILE}" |,或者 (b) 使用临时文件并将其移动到位。后者有一个优势,如果替换由于任何原因失败,它可能会在原始文件被覆盖(并丢失)之前失败。第一种方法可以覆盖文件。第三种选择是执行sed -i -e "s/..." "${FILE}",它会在文件中就地更改......虽然这并不总是有效,具体取决于操作系统版本,sed 等。
  • (或者“就地”限制可能是底层文件系统的一个因素,我不确定。我只知道我遇到了无法使用-i 的情况。 )

标签: bash shell variables pipe


【解决方案1】:

如果你只是想用 foo.txt 生成带有控制字符的 foo.aiff,你可以这样做:

#!/bin/sh

for file; do
  test "${file%.txt}" = "${file}" && continue
  sed -e 's/\..*$/[[slnc 2000]]/' "$file" | 
    sed -e 's/$/[[slnc 2000]]/' | 
    say -v Alex -o "${file%.txt}".aiff
done

使用您的 .txt 文件作为参数调用脚本(例如,./myscript *.txt),它将生成.aiff 文件。请注意,如果say 覆盖文件,那么也会如此。您实际上并不需要两次 sed 调用,并且可以清理您调用的 sed,但我不想分散这里的核心问题,所以我将其保留为您所拥有的。

【讨论】:

    【解决方案2】:

    这将:-

    a} 使用 find 列出要在当前目录中处理的文本文件。

    b} 将您的 sed 命令应用于列表中的每个文本文件,但仅限于当前使用,让您可以完整地保留它们。

    c} 用编辑过的文件调用“say”。

    我没有发言权,所以我无法测试那个或控制代码;但只要你有 Ed,循环就可以工作。我已经用过很多次了。我是通过接触 FORTH 来学习它的,这是一种仍然允许未终止循环的语言。我曾经在记住在脚本末尾调用 next 以启动它时遇到问题,但是我通过首先以 FORTH 样式定义我的单词(函数)然后总是将我的一次性命令放在结束。

    #!/bin/sh
    
    next() {
    [[ -s stack ]] && main
    end
    }
    
    main() {
    line=$(ed -s stack < edprint+.txt)
    infile=$(cat "${line}" | sed 's/\..*$/[[slnc 2000]]/' | sed 's/$/[[slnc 2000]]/')
    say "${infile}" -v Alex -o input.aiff
    ed -s stack < edpop+.txt
    next
    }
    
    end() {
    rm -v ./stack
    rm -v ./edprint+.txt
    rm -v ./edpop+.txt
    exit 0
    }
    
    find *.txt -type -f > stack
    
    cat >> edprint+.txt << EOF
    1
    q
    EOF
    
    cat >> edpop+.txt << EOF
    1d
    wq
    EOF
    
    next
    

    【讨论】:

      猜你喜欢
      • 2015-04-17
      • 2021-12-10
      • 2019-03-24
      • 2022-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      相关资源
      最近更新 更多