2017-02-18 34 views
1

我必须在bash语言中编写ubuntu linux中的脚本,它必须在命令行中使用三个参数:第一个文件的名称,其行必须排序,第二个文件(如果我想要按字母顺序排序升序或'z',如果我想按字母顺序排序降序)和第三个正数'n'。我只需要排序多个'n'的行。例如,如果我有一个100行和n = 5的文本文件,那么我只需要排序行5,10,15,...,100,其余的必须保持不变。这可以做到吗? 我能找到和多个“n”的这样的线路进行排序:(bash脚本)如何对文件中'n'位置倍数的行进行排序?

awk "NR%$n==0" archivo.txt | sort -f 

,但现在我不知道该怎么写一遍这些行到文件中。

感谢您的关注

+1

向我们展示你到目前为止所拥有的。 –

+0

我可以找到'n'的倍数的行,并像这样排序:awk“NR%$ n == 0”file.txt | sort -f但现在我不能再将这些行再次引入到文件中。 –

+0

仅供参考,这将更好地写为'awk -v n =“$ n”'NR%n == 0'';使用字符串替换来生成脚本(使用任何语言 - 不仅仅是awk,还包括bash,SQL等)显然是不安全的,而不是从代码中带外传递数据。 –

回答

1

毫无疑问,这可能会在纯awk进行为好,但低于使用本机的bash:

#!/usr/bin/env bash 

input=${1:-archivo.txt} # set input to $1, or default to archivo.txt 
n=${2:-5}    # set n to $2, or default to 5 
i=0      # initialize line counter to 0 

while IFS= read -r line <&3; do # always read from input on FD 3 
    if ((i % n == 0)); then  # if we're on a line being sorted... 
    IFS= read -r line <&4  # ...overwrite $line from the awk | sort process on FD 4 
    fi 
    printf '%s\n' "$line"   # write out whatever we most recently read 
    ((++i))      # increment line counter 
done 3<"$input" 4< <(awk -v "n=$n" 'NR%n==0' <"$input" | sort -f) 

一些注意事项:

  • 使用shebang在冷杉明确地调用bash(不是sh) t脚本确保扩展可用。
  • <(awk ...)是一个进程替换 - 它的计算结果是一个文件名,当它被读取时,将提供awk命令的输出。 4<将该文件的内容连接到文件描述符#4。
  • (())创建算术上下文,并且是由ksh和bash提供的扩展(与由POSIX保证的$(())相比)。
  • 有关为什么read被调用的方式(已清除IFS并通过了-r参数),请参阅BashFAQ #001
  • 使用awk -v "var=$var" 'awk script using var'避免错误,并能形成与字符串连接脚本时引起的注入漏洞
+0

不要忘记-u选项以供读取,例如。IFS = read -r line -u4 – grail

+0

该代码不起作用,也许它有一个错误,但我找不到它 –

+0

@CharlesDuffy我看到你正在使用重定向而不是'read'的'-u'选项便携性我认为)。如果shell是Bash,使用'-u'有什么优点/缺点? – Fred

1

你可以使用GAWK,如果你不介意整个输入文件扔到内存中,以便线的子集可以在打印之前进行排序。

$ ./sortthing -v inc=5 inputfile 

注意,这里使用了GAWK功能asort(),这并不在一个真实的awk中存在:

#!/usr/bin/env gawk -f 

BEGIN { 
    if (!inc) inc=5    # set a default 
} 

NR%inc { 
    # This is a normal line 
    nosort[NR]=$0 
    next 
} 

{ 
    # This is an increment of "inc" 
    tosort[NR]=$0 
} 

END { 
    # Sort the array of increments 
    asort(tosort) 

    # Step through our two arrays, picking what to print based on the modulo 
    n=0 
    for (i=1; i<NR; i++) 
    if (i%inc==0) 
     print tosort[++n] 
    else 
     print nosort[i] 
} 

你可能会喜欢的东西运行此。因此,如果您在* BSD或OS X上执行此操作,则可能需要安装其他工具。

相关问题