2017-02-18 35 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上執行此操作,則可能需要安裝其他工具。

相關問題