【问题标题】:Bash tool to get nth line from a fileBash工具从文件中获取第n行
【发布时间】:2011-08-26 17:09:26
【问题描述】:

有这样做的“规范”方式吗?我一直在使用 head -n | tail -1 来解决问题,但我一直想知道是否有一个 Bash 工具可以专门从文件中提取一行(或一系列行)。

我所说的“规范”是指其主要功能正在执行此操作的程序。

【问题讨论】:

  • “Unix 方式”是把能做好各自工作的工具链接起来。所以我想你已经找到了一个非常合适的方法。其他方法包括awksed,我相信有人也可以想出一个 Perl 单行代码;)
  • 双命令表明head | tail 解决方案不是最佳的。已经提出了其他更接近最佳的解决方案。
  • 您是否针对平均情况下最快的解决方案进行了基准测试?
  • cat line X to line Y on a huge file Unix & Linux 上的基准(范围)。 (cc @Marcin,以防两年多后你仍然想知道)
  • head | tail 解决方案不起作用,如果您查询输入中不存在的行:它将打印最后一行。

标签: bash shell unix awk sed


【解决方案1】:

head 和带有tail 的管道对于大文件来说会很慢。我建议像这样sed

sed 'NUMq;d' file

其中NUM 是您要打印的行号;例如,sed '10q;d' file 打印file 的第 10 行。

解释:

当行号为NUM时,NUMq会立即退出。

d 将删除该行而不是打印它;这在最后一行被禁止,因为q 导致退出时跳过脚本的其余部分。

如果变量中有NUM,则需要使用双引号而不是单引号:

sed "${NUM}q;d" file

【讨论】:

  • 对于那些想知道的人来说,这个解决方案似乎比下面提出的 sed -n 'NUMp'sed 'NUM!d' 解决方案快 6 到 9 倍。
  • 我认为tail -n+NUM file | head -n1 可能会一样快或更快。至少,当我在一个有 50 万行的文件上尝试 NUM 为 250000 时,它在我的系统上(显着)更快。 YMMV,但我真的不明白为什么会这样。
  • 不,不是。如果没有q,它将处理完整文件
  • @Fiddlestiques:别忘了引用 foo="$(sed "4q;d" file4)"
  • @anubhava - 谢谢 - 现在知道了 - echo "$foo" 而不是 echo $foo
【解决方案2】:
sed -n '2p' < file.txt

将打印第二行

sed -n '2011p' < file.txt

2011 行

sed -n '10,33p' < file.txt

第 10 行到第 33 行

sed -n '1p;3p' < file.txt

第 1 行和第 3 行

等等……

要使用 sed 添加行,您可以检查:

sed: insert a line in a certain position

【讨论】:

  • 为什么在这种情况下需要'
  • @RafaelBarbosa &lt; 在这种情况下是不必要的。简单地说,我更喜欢使用重定向,因为我经常使用像sed -n '100p' &lt; &lt;(some_command) 这样的重定向——所以,通用语法:)。它的效果并不差,因为在分叉时使用 shell 完成重定向,所以......这只是一种偏好......(是的,它长了一个字符):)
  • @jm666 实际上它长了 2 个字符,因为您通常会在
  • @rasen58 空格也是字符吗? :) /好吧,开个玩笑-你说得对/ :)
  • 在读取 50M 行的文件时,这比尾部/头部组合慢约 5 倍
【解决方案3】:

您也可以为此使用 Perl:

perl -wnl -e '$.== NUM && print && exit;' some.file

【讨论】:

  • 在对包含 6,000,000 行的文件进行测试并检索任意行 #2,000,000 时,此命令几乎是即时的,并且比 sed 答案快得多。
【解决方案4】:

您也可以使用 sed 打印并退出:

sed -n '10{p;q;}' file   # print line 10

【讨论】:

  • -n 选项禁用打印每一行的默认操作,您肯定会通过快速浏览手册页发现。
  • GNU sed 中,所有 sed 答案的速度都差不多。因此(对于 GNU sed)这是最好的 sed 答案,因为它可以节省大文件和小 nth line 值的时间。
【解决方案5】:

哇,所有的可能性!

试试这个:

sed -n "${lineNum}p" $file

或其中之一,取决于您的 Awk 版本:

awk  -vlineNum=$lineNum 'NR == lineNum {print $0}' $file
awk -v lineNum=4 '{if (NR == lineNum) {print $0}}' $file
awk '{if (NR == lineNum) {print $0}}' lineNum=$lineNum $file

您可能需要尝试nawkgawk 命令)。

是否有只打印特定行的工具?不是标准工具之一。但是,sed 可能是最接近且最容易使用的。

【讨论】:

    【解决方案6】:

    awk 相当快:

    awk 'NR == num_line' file
    

    如果为真,则执行awk 的默认行为:{print $0}


    替代版本

    如果你的文件很大,你最好在阅读完所需的行后exit。这样可以节省 CPU 时间请参阅答案末尾的时间比较

    awk 'NR == num_line {print; exit}' file
    

    如果你想从 bash 变量中给出行号,你可以使用:

    awk 'NR == n' n=$num file
    awk -v n=$num 'NR == n' file   # equivalent
    

    查看使用exit 节省了多少时间,特别是如果该行恰好位于文件的第一部分:

    # Let's create a 10M lines file
    for ((i=0; i<100000; i++)); do echo "bla bla"; done > 100Klines
    for ((i=0; i<100; i++)); do cat 100Klines; done > 10Mlines
    
    $ time awk 'NR == 1234567 {print}' 10Mlines
    bla bla
    
    real    0m1.303s
    user    0m1.246s
    sys 0m0.042s
    $ time awk 'NR == 1234567 {print; exit}' 10Mlines
    bla bla
    
    real    0m0.198s
    user    0m0.178s
    sys 0m0.013s
    

    因此差异是 0.198 秒与 1.303 秒,大约快 6 倍。

    【讨论】:

    • 这种方法总是会比较慢,因为 awk 会尝试进行字段拆分。字段拆分的开销可以减少awk 'BEGIN{FS=RS}(NR == num_line) {print; exit}' file
    • 当您想要连接 file1 的 n1 行、file2 的 n2 行、n3 或 file3 ...awk 'FNR==n' n=10 file1 n=30 file2 n=60 file3 时,这种方法中 awk 的真正威力就显现出来了。使用 GNU awk 可以使用 awk 'FNR==n{print;nextfile}' n=10 file1 n=30 file2 n=60 file3 加速。
    • @kvantour 确实,GNU awk 的 nextfile 非常适合此类事情。 FS=RS 如何避免字段拆分?
    • FS=RS并没有避免字段拆分,而是只解析$0的,只分配一个字段,因为$0中没有RS
    • @kvantour 我一直在用FS=RS 进行一些测试,并没有看到时间上的差异。我问一个关于它的问题怎么样,这样你就可以扩展?谢谢!
    【解决方案7】:

    这个问题被标记为 Bash,这是 Bash (≥4) 的做法:使用 mapfile-s(跳过)和 -n(计数)选项。

    如果需要获取文件file的第42行:

    mapfile -s 41 -n 1 ary < file
    

    此时,您将拥有一个数组 ary,其字段包含 file 的行(包括尾随换行符),我们跳过了前 41 行 (-s 41),并停止读完一行(-n 1)。所以这真的是第 42 行。打印出来:

    printf '%s' "${ary[0]}"
    

    如果您需要一系列行,请说范围 42–666(含),并说您不想自己进行数学运算,并将它们打印到标准输出上:

    mapfile -s $((42-1)) -n $((666-42+1)) ary < file
    printf '%s' "${ary[@]}"
    

    如果您也需要处理这些行,那么存储尾随换行符并不是很方便。在这种情况下,使用-t 选项(修剪):

    mapfile -t -s $((42-1)) -n $((666-42+1)) ary < file
    # do stuff
    printf '%s\n' "${ary[@]}"
    

    你可以让一个函数为你做这件事:

    print_file_range() {
        # $1-$2 is the range of file $3 to be printed to stdout
        local ary
        mapfile -s $(($1-1)) -n $(($2-$1+1)) ary < "$3"
        printf '%s' "${ary[@]}"
    }
    

    没有外部命令,只有 Bash 内置命令!

    【讨论】:

      【解决方案8】:

      使用 sed 打印第 n 行,并将变量作为行号:

      a=4
      sed -e $a'q:d' file
      

      这里的“-e”标志用于将脚本添加到要执行的命令中。

      【讨论】:

      • 冒号是语法错误,应该是分号。
      【解决方案9】:

      大文件最快的解决方案总是tail|head,前提是两个距离:

      • 从文件的开头到起始行。让我们称之为S
      • 从最后一行到文件末尾的距离。就这样E

      众所周知。然后,我们可以使用这个:

      mycount="$E"; (( E > S )) && mycount="+$S"
      howmany="$(( endline - startline + 1 ))"
      tail -n "$mycount"| head -n "$howmany"
      

      howman 只是所需的行数。

      更多细节在https://unix.stackexchange.com/a/216614/79743

      【讨论】:

      • 请说明SE 的单位(即字节、字符或行)。
      【解决方案10】:

      如果您有多个由 \n 分隔的行(通常是新行)。你也可以使用'cut':

      echo "$data" | cut -f2 -d$'\n'
      

      您将从文件中获得第二行。 -f3 给你第三行。

      【讨论】:

      • 也可用于显示多行:cat FILE | cut -f2,5 -d$'\n' 将显示文件的第 2 行和第 5 行。 (但它不会保留顺序。)
      【解决方案11】:

      我有一个独特的情况,我可以对本页上提出的解决方案进行基准测试,所以我写这个答案是为了整合所提出的解决方案,并包含每个解决方案的运行时间。

      设置

      我有一个 3.261 GB 的 ASCII 文本数据文件,每行有一个键值对。该文件总共包含 3,339,550,320 行,并且无法在我尝试过的任何编辑器中打开,包括我的首选 Vim。我需要对这个文件进行子集化,以调查我发现的一些值仅从 ~500,000,000 行开始。

      因为文件有这么多行:

      • 我只需要提取行的子集来对数据执行任何有用的操作。
      • 通读每一行导致我关心的值需要很长时间。
      • 如果解决方案读取了我关心的行并继续读取文件的其余部分,它将浪费时间读取近 30 亿行不相关的行,并且花费的时间比必要时间长 6 倍。

      我的最佳情况是一种解决方案,它只从文件中提取一行而不读取文件中的任何其他行,但我想不出如何在 Bash 中完成此操作。

      为了我的理智,我不会尝试阅读我自己的问题所需的全部 500,000,000 行。相反,我将尝试从 3,339,550,320 行中提取第 50,000,000 行(这意味着读取完整文件所需的时间比必要的长 60 倍)。

      我将使用内置的time 对每个命令进行基准测试。

      基线

      首先让我们看看headtail是如何解决的:

      $ time head -50000000 myfile.ascii | tail -1
      pgm_icnt = 0
      
      real    1m15.321s
      

      第 5000 万行的基线是 00:01:15.321,如果我直接进入第 50000 万行,可能需要约 12.5 分钟。

      剪切

      我对此表示怀疑,但值得一试:

      $ time cut -f50000000 -d$'\n' myfile.ascii
      pgm_icnt = 0
      
      real    5m12.156s
      

      这个跑了00:05:12.156,比基线慢很多!我不确定它是在停止之前读取整个文件还是仅读取 5000 万行,但无论如何,这似乎不是解决问题的可行方案。

      AWK

      我只使用exit 运行解决方案,因为我不会等待完整的文件运行:

      $ time awk 'NR == 50000000 {print; exit}' myfile.ascii
      pgm_icnt = 0
      
      real    1m16.583s
      

      此代码在 00:01:16.583 中运行,仅慢了约 1 秒,但在基线上仍然没有改进。按照这个速度,如果排除了退出命令,读取整个文件可能需要大约 76 分钟!

      Perl

      我也运行了现有的 Perl 解决方案:

      $ time perl -wnl -e '$.== 50000000 && print && exit;' myfile.ascii
      pgm_icnt = 0
      
      real    1m13.146s
      

      此代码在 00:01:13.146 中运行,比基线快约 2 秒。如果我在全部 500,000,000 上运行它可能需要大约 12 分钟。

      sed

      板上的最佳答案,这是我的结果:

      $ time sed "50000000q;d" myfile.ascii
      pgm_icnt = 0
      
      real    1m12.705s
      

      此代码在 00:01:12.705 运行,比基线快 3 秒,比 Perl 快约 0.4 秒。如果我在完整的 500,000,000 行上运行它可能需要大约 12 分钟。

      地图文件

      我有 bash 3.1,因此无法测试 mapfile 解决方案。

      结论

      在大多数情况下,似乎很难改进 head tail 解决方案。 sed 解决方案最多可将效率提高约 3%。

      (使用公式% = (runtime/baseline - 1) * 100计算的百分比)

      第 50,000,000 行

      1. 00:01:12.705 (-00:00:02.616 = -3.47%)sed
      2. 00:01:13.146 (-00:00:02.175 = -2.89%) perl
      3. 00:01:15.321 (+00:00:00.000 = +0.00%) head|tail
      4. 00:01:16.583 (+00:00:01.262 = +1.68%) awk
      5. 00:05:12.156 (+00:03:56.835 = +314.43%) cut

      第 500,000,000 行

      1. 00:12:07.050 (-00:00:26.160) sed
      2. 00:12:11.460 (-00:00:21.750) perl
      3. 00:12:33.210 (+00:00:00.000) head|tail
      4. 00:12:45.830 (+00:00:12.620) awk
      5. 00:52:01.560 (+00:40:31.650) cut

      第 3,338,559,320 行

      1. 01:20:54.599 (-00:03:05.327) sed
      2. 01:21:24.045 (-00:02:25.227) perl
      3. 01:23:49.273 (+00:00:00.000) head|tail
      4. 01:25:13.548 (+00:02:35.735) awk
      5. 05:47:23.026 (+04:24:26.246) cut

      【讨论】:

      • 我想知道将整个文件放入 /dev/null 需要多长时间。 (如果这只是一个硬盘基准测试呢?)
      • 我有一种反常的冲动,要对您拥有 3+ gig 文本文件字典的所有权低头。无论是什么原理,这都包含文本性:)
      • 使用head + tail 运行两个进程的开销对于单个文件来说可以忽略不计,但是当您对多个文件执行此操作时就会开始显示。
      【解决方案12】:

      根据我的测试,在性能和可读性方面,我的建议是:

      tail -n+N | head -1

      N 是您想要的行号。例如,tail -n+7 input.txt | head -1 将打印文件的第 7 行。

      tail -n+N 将从N 行开始打印所有内容,head -1 将在一行后停止。


      替代的head -N | tail -1 可能更具可读性。例如,这将打印第 7 行:

      head -7 input.txt | tail -1

      在性能方面,较小尺寸的差异不大,但当文件变大时,它的性能将优于tail | head(上图)。

      投票率最高的sed 'NUMq;d' 很有趣,但我认为与头/尾解决方案相比,开箱即用的人会更少,而且它也比尾/头慢。

      在我的测试中,两个尾部/头部版本的性能始终优于 sed 'NUMq;d'。这与发布的其他基准一致。很难找到反面/正面非常糟糕的情况。这也不足为奇,因为这些是您期望在现代 Unix 系统中进行大量优化的操作。

      为了了解性能差异,以下是我为大文件 (9.3G) 获得的数字:

      • tail -n+N | head -1:3.7 秒
      • head -N | tail -1:4.6 秒
      • sed Nq;d:18.8 秒

      结果可能会有所不同,但head | tailtail | head 的性能通常与较小的输入相当,而sed 的速度总是慢很多(大约 5 倍左右)。

      要重现我的基准,您可以尝试以下操作,但要注意它会在当前工作目录中创建一个 9.3G 文件:

      #!/bin/bash
      readonly file=tmp-input.txt
      readonly size=1000000000
      readonly pos=500000000
      readonly retries=3
      
      seq 1 $size > $file
      echo "*** head -N | tail -1 ***"
      for i in $(seq 1 $retries) ; do
          time head "-$pos" $file | tail -1
      done
      echo "-------------------------"
      echo
      echo "*** tail -n+N | head -1 ***"
      echo
      
      seq 1 $size > $file
      ls -alhg $file
      for i in $(seq 1 $retries) ; do
          time tail -n+$pos $file | head -1
      done
      echo "-------------------------"
      echo
      echo "*** sed Nq;d ***"
      echo
      
      seq 1 $size > $file
      ls -alhg $file
      for i in $(seq 1 $retries) ; do
          time sed $pos'q;d' $file
      done
      /bin/rm $file
      

      这是在我的机器上运行的输出(ThinkPad X1 Carbon,带有 SSD 和 16G 内存)。我假设在最终运行中,所有内容都来自缓存,而不是磁盘:

      *** head -N | tail -1 ***
      500000000
      
      real    0m9,800s
      user    0m7,328s
      sys     0m4,081s
      500000000
      
      real    0m4,231s
      user    0m5,415s
      sys     0m2,789s
      500000000
      
      real    0m4,636s
      user    0m5,935s
      sys     0m2,684s
      -------------------------
      
      *** tail -n+N | head -1 ***
      
      -rw-r--r-- 1 phil 9,3G Jan 19 19:49 tmp-input.txt
      500000000
      
      real    0m6,452s
      user    0m3,367s
      sys     0m1,498s
      500000000
      
      real    0m3,890s
      user    0m2,921s
      sys     0m0,952s
      500000000
      
      real    0m3,763s
      user    0m3,004s
      sys     0m0,760s
      -------------------------
      
      *** sed Nq;d ***
      
      -rw-r--r-- 1 phil 9,3G Jan 19 19:50 tmp-input.txt
      500000000
      
      real    0m23,675s
      user    0m21,557s
      sys     0m1,523s
      500000000
      
      real    0m20,328s
      user    0m18,971s
      sys     0m1,308s
      500000000
      
      real    0m19,835s
      user    0m18,830s
      sys     0m1,004s
      

      【讨论】:

      • head | tailtail | head 之间的性能是否不同?还是取决于正在打印哪一行(文件开头与文件结尾)?
      • @wisbucky 我没有确切的数字,但首先使用 tail 后跟“head -1”的一个缺点是您需要提前知道总长度。如果您不知道,则必须先计算它,这将在性能方面有所损失。另一个缺点是使用起来不太直观。例如,如果您有数字 1 到 10 并且想要获得第 3 行,则必须使用“tail -8 | head -1”。这比“head -3 | tail -1”更容易出错。
      • 对不起,我应该包括一个例子来清楚。 head -5 | tail -1tail -n+5 | head -1。实际上,我找到了另一个进行测试比较的答案,发现tail | head 更快。 stackoverflow.com/a/48189289
      • @wisbucky 感谢您提及!我做了一些测试,不得不同意它总是稍微快一点,与我所看到的线的位置无关。鉴于此,我改变了我的答案,并且还包括了基准,以防有人想要复制它。
      【解决方案13】:

      以上所有答案都直接回答了问题。但这是一个不太直接的解决方案,但可能是一个更重要的想法,可以引发思考。

      由于行长是任意的,所以文件第 n 行之前的所有字节都需要被读取。如果您有一个巨大的文件或需要多次重复此任务,并且此过程很耗时,那么您应该首先认真考虑是否应该以不同的方式存储数据。

      真正的解决方案是有一个索引,例如在文件的开头,指示行开始的位置。您可以使用数据库格式,或者只是在文件开头添加一个表。或者,创建一个单独的索引文件来伴随您的大文本文件。

      例如您可以为换行创建一个字符位置列表:

      awk 'BEGIN{c=0;print(c)}{c+=length()+1;print(c+1)}' file.txt > file.idx
      

      然后用tail 读取,实际上seeks 直接指向文件中的适当点!

      例如获取第 1000 行:

      tail -c +$(awk 'NR=1000' file.idx) file.txt | head -1
      
      • 这可能不适用于 2 字节/多字节字符,因为 awk 可以“识别字符”,但 tail 不能。
      • 我还没有针对大文件对此进行过测试。
      • 另见this answer
      • 或者 - 将您的文件拆分为更小的文件!

      【讨论】:

        【解决方案14】:

        已经有很多好的答案了。我个人选择awk。为方便起见,如果您使用 bash,只需将以下内容添加到您的 ~/.bash_profile。而且,下次您登录时(或者如果您在此更新后获取 .bash_profile),您将拥有一个新的漂亮的“nth”函数来通过管道传输您的文件。

        执行此操作或将其放入您的 ~/.bash_profile(如果使用 bash)并重新打开 bash(或执行 source ~/.bach_profile

        # print just the nth piped in line
        nth () { awk -vlnum=${1} 'NR==lnum {print; exit}'; } 
        

        然后,要使用它,只需通过管道即可。例如:

        $ yes line | cat -n | nth 5
             5  line
        

        【讨论】:

          【解决方案15】:

          作为 CaffeineConnoisseur 非常有用的基准测试答案的后续行动...我很好奇“mapfile”方法与其他方法相比有多快(因为未经测试),所以我尝试了快速而肮脏的速度比较自己,因为我确实有 bash 4。当我在上面的时候,对顶部答案中的一个 cmets 中提到的“tail | head”方法(而不是 head | tail)进行了测试,因为人们正在歌颂它。我没有任何接近使用的测试文件大小的东西;我能在短时间内找到的最好的文件是一个 14M 的谱系文件(用空格分隔的长行,不到 12000 行)。

          短版:mapfile 看起来比 cut 方法快,但比其他所有方法都慢,所以我称之为哑巴。尾巴 | head, OTOH,看起来它可能是最快的,虽然对于这种大小的文件,与 sed 相比差异并不是那么大。

          $ time head -11000 [filename] | tail -1
          [output redacted]
          
          real    0m0.117s
          
          $ time cut -f11000 -d$'\n' [filename]
          [output redacted]
          
          real    0m1.081s
          
          $ time awk 'NR == 11000 {print; exit}' [filename]
          [output redacted]
          
          real    0m0.058s
          
          $ time perl -wnl -e '$.== 11000 && print && exit;' [filename]
          [output redacted]
          
          real    0m0.085s
          
          $ time sed "11000q;d" [filename]
          [output redacted]
          
          real    0m0.031s
          
          $ time (mapfile -s 11000 -n 1 ary < [filename]; echo ${ary[0]})
          [output redacted]
          
          real    0m0.309s
          
          $ time tail -n+11000 [filename] | head -n1
          [output redacted]
          
          real    0m0.028s
          

          希望这会有所帮助!

          【讨论】:

            【解决方案16】:

            使用其他人提到的内容,我希望这是我的 bash shell 中的一个快速且花哨的功能。

            创建文件:~/.functions

            添加内容:

            getline() { line=$1 sed $line'q;d' $2 }

            然后将此添加到您的~/.bash_profile

            source ~/.functions

            现在当你打开一个新的 bash 窗口时,你可以像这样调用函数:

            getline 441 myfile.txt

            【讨论】:

            • 在使用之前无需将$1 分配给另一个变量,并且您正在破坏任何其他全局line。在 Bash 中,对函数变量使用local;但在这里,如前所述,可能只是做sed "$1d;q" "$2"。 (另请注意"$2" 的引用。)
            • 正确,但拥有自我记录的代码可能会有所帮助。
            【解决方案17】:

            我已将上述一些答案放入一个简短的 bash 脚本中,您可以将其放入名为 get.sh 的文件中并链接到 /usr/local/bin/get(或您喜欢的任何其他名称)。

            #!/bin/bash
            if [ "${1}" == "" ]; then
                echo "error: blank line number";
                exit 1
            fi
            re='^[0-9]+$'
            if ! [[ $1 =~ $re ]] ; then
                echo "error: line number arg not a number";
                exit 1
            fi
            if [ "${2}" == "" ]; then
                echo "error: blank file name";
                exit 1
            fi
            sed "${1}q;d" $2;
            exit 0
            

            确保它是可执行的

            $ chmod +x get
            

            链接它以使其在PATH 上可用

            $ ln -s get.sh /usr/local/bin/get
            

            【讨论】:

              【解决方案18】:

              在查看了the top answerthe benchmark 之后,我实现了一个小助手函数:

              function nth {
                  if (( ${#} < 1 || ${#} > 2 )); then
                      echo -e "usage: $0 \e[4mline\e[0m [\e[4mfile\e[0m]"
                      return 1
                  fi
                  if (( ${#} > 1 )); then
                      sed "$1q;d" $2
                  else
                      sed "$1q;d"
                  fi
              }
              

              基本上你可以通过两种方式使用它:

              nth 42 myfile.txt
              do_stuff | nth 42
              

              【讨论】:

                【解决方案19】:

                保存两次击键,不使用括号打印第N行:

                sed  -n  Np  <fileName>
                      ^   ^
                       \   \___ 'p' for printing
                        \______ '-n' for not printing by default 
                

                例如,打印第 100 行:

                sed -n 100p foo.txt      
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-11-08
                  • 1970-01-01
                  • 2015-07-13
                  • 2015-10-28
                  相关资源
                  最近更新 更多