在 bash 脚本中需要有关字符串操作的帮助

Need help for string manipulation in a bash script

我不习惯 bash 脚本的语法。我正在尝试读取文件。对于每一行,我只想保留定界符“/”之前的字符串部分,如果单词符合特定长度,则将其放回新文件中。我下载了一本字典,但格式不符合我的预期。由于有 84000 个单词,我真的不想手动删除每个单词的“/”之后的内容。我虽然这很容易,但我在这个网站上的其他类似问题中遵循了几个想法,但似乎我在某处遗漏了一些东西,因为它仍然不起作用。长度不对啊文件 Test_Input 每行包含一个单词。这是代码:

#!/usr/bin/bash
filename="Test_Input.txt"
while read -r line
do
    sub= echo $line | cut -d '/' -f1
    length= echo ${#sub}
    if $length >= 4 && $length <= 10;
        then echo $sub >> Test_Output.txt
    fi
done < "$filename"

几项:

  1. 我假设您一直在作业中使用单反引号,而不是字面上的 sub= echo $line | cut -d '/' -f1,因为这肯定会失败。或者,您也可以使用 sub=$(),如 $(echo $line | cut -d '/' -f1)
  2. if 子句中的条件需要包含在单或双 [] 中,例如:if [[ $length -ge 4 ]] && [[ $length -le 10 ]];
  3. 这让我想到了下一点:<= 在 bash 中无法可靠地工作。只需对 "greater or equal" 使用 -ge,对 "less or equal" 使用 -le
  4. 如果您的行不包含任何 / 个字符,在您的版本中 sub 将包含整行。这可能不是你想要的,所以我建议也将 -s 标志添加到 cut.
  5. 您不需要 somevar=$(echo $someothervar)。只需使用 somevar=$someothervar

这是一个有效的版本:

#!/usr/bin/env bash
filename="Test_Input.txt"
while read -r line
do
    sub=$(echo $line | cut -s -d '/' -f 1)
    length=${#sub}
    if [[ $length -ge 4 ]] && [[ $length -le 10 ]];
        then echo $sub >> Test_Output.txt
    fi
done < "$filename"

当然你也可以只用sed:

sed -n -r '/^[^/]{4,10}\// s;/.*$;;p' Test_Input.txt > Test_Output.txt

解释:

  • -n 除非明确标记为打印,否则不要打印任何内容。
  • -r 使用扩展正则表达式
  • /<searchterm>/ <operation> 搜索符合特定条件的行,并执行此操作:
    • Searchterm 是:^[^/]{4,10}\/ 从行的开头开始,应该有 4 到 10 个非斜杠字符,然后是斜杠
    • 操作是:s;/.*$;;p将第一个斜杠和行尾之间的所有内容替换为空,然后打印。

awk 是最好的工具

awk -F/ 'length() >= 4 && length() <= 10 {print } > newfile