如何使用tail和head获取带有Tab标签的行

时间:2016-01-25 23:56:01

标签: bash

我已经制作了一个脚本来练习我的Bash,只是意识到这个脚本没有考虑制表,这是一个问题,因为它旨在查找和替换Python脚本中的模式(显然需要制表到工作)。

这是我的代码。有没有一种简单的方法来解决这个问题?

pressure=1
nline=$(cat /myfile.py | wc -l) # find the line length of the file
echo $nline
for ((c=0;c<=${nline};c++)) 
do
    res=$( tail -n $(($(($nline+1))-$c)) myfile.py | head -n 1 | awk 'gsub("="," ",$1){print $1}' | awk '{print$1}') 
    #echo $res
    if [ $res == 'pressure_run' ]
    then 
        echo "pressure_run='${pressure}'" >> myfile_mod.py
    else 
        echo $( tail -n $(($nline-$c)) myfile.py | head -n 1) >> myfile_mod.py
    fi
done

基本上,它会找到包含pressure_run=something的行,并将其替换为pressure_run=$pressure。文件的其余部分应该不受影响。但在这种情况下,所有制表都会被删除。

1 个答案:

答案 0 :(得分:2)

如果您想尽快进行更换,请按照shellter评论中指出的方式选择sed:

sed "s/\(pressure_run=\).*/\1$pressure/" myfile.py

对于Bash培训,正如您所说,您可能希望在您的文件上手动循环。您当前版本的一些评论:

  • /myfile.py真的在根目录中吗?之后,你不会在那个地方引用它。
  • cat ... | wc -luseless use of cat,最好写成wc -l < myfile.py
  • 您的for循环执行的时间比您的行多一次。
  • 要获得下一行,你会向我显示所有行,但从后面算起,不要显示c行,然后告诉我这些行的第一行&# 34 ;. 必须更简单,对吗?
  • 要获得作业左侧的内容,请在第一个以空格分隔的字段中说“=替换为空格,然后显示我结果的第一个空格分隔字段&#34;。 必须是一种更简单的方式,对吗?顺便说一下,这是你去除前导标签的地方(你的第一个awk命令就是这样做的。)
  • 要打印未更改的行,您可以执行与以前相同的复杂操作。

创可贴解决方案

可以获得所需结果的最小变化是修改awk命令:而不是

awk 'gsub("="," ",$1){print $1}' | awk '{print$1}'

你可以使用

awk -F '=' '{ print $1 }'

&#34;字段由=分隔;给我第一个&#34;。这保留了主要标签。

替换也必须稍微调整一下;您现在想要匹配pressure_run结束的内容:

if [[ $res == *pressure_run ]]

我使用了更灵活的[[ ]]代替[ ],并将*添加到pressure_run(必须引用):&#34;如果$respressure_run结束,那么......&#34;

替换必须使用$res,其中包含适当数量的标签:

echo "$res='${pressure}'" >> myfile_mod.py

您可以使用done > myfile_mod.py重定向整个循环的输出,而不是每个循环追加每一行(并每次打开文件)。

这与您的版本中的字面${pressure}一样,因为它是单引号。如果你想用$pressure的值替换它,你必须删除单引号(这里不需要括号,但不要伤害):

echo "$res=$pressure" >> myfile_mod.py

这修复了你的例子,但应该指出的是,枚举行然后用tail | head一次获取一行是一个非常糟糕的主意。您遍历文件的每一行两次,它非常容易出错并且难以阅读。 (感谢tripleee建议更清楚地提及这一点。)

正确的解决方案

总而言之,有一些首选的方法可以做你做的事情。你基本上循环遍历一个文件,如果一行符合pressure_run=,你想用$pressure(或该变量的值)替换右边的内容。我将如何做到这一点:

#!/bin/bash

pressure=1

# Regular expression to match lines we want to change
re='^[[:space:]]*pressure_run='

# Read lines from myfile.py
while IFS= read -r line; do

    # If the line matches the regular expression
    if [[ $line =~ $re ]]; then

        # Print what we matched (with whitespace!), then the value of $pressure
        line="${BASH_REMATCH[0]}"$pressure
    fi

    # Print the (potentially modified) line
    echo "$line"

# Read from myfile.py, write to myfile_mod.py
done < myfile.py > myfile_mod.py

对于看起来像

的测试文件
blah
   test

pressure_run=no_tab
    blah

something
    pressure_run=one_tab
        pressure_run=two_tabs

结果是

blah
   test

pressure_run=1
    blah

something
    pressure_run=1
        pressure_run=1

推荐阅读