Shell 中的排序循环

发布于 2024-12-22 06:34:36 字数 446 浏览 1 评论 0原文

我有一个正常的...

for file in *
do
    #do something here
done

...代码。 问题是我想按自定义日期对文件行进行排序,该日期是在文件的第二行中定义的。 我在这里遇到了问题:

1. 在实际运行之前,如何找出这些多个文件的第二行中的内容

for file in * do

2. 那么如何按此自定义字符串对循环进行排序?

这不起作用,但也许它会帮助您理解我的问题:

for file in *
do
    customdate="$(sed -n 2p $file)"
done

for file in * sort by $customdate
do
    #do something here
done

I have a normal...

for file in *
do
    #do something here
done

...Code.
The problem is that I want to sort the row of the files by a custom date, the date is defined in the second line of the files.
I got to problems here:

1.How do I find out what's in the second line of these multiple files before I actually run

for file in * do

2.How do I sort the loop by this custom string then?

This doesn't work but maybe it will help you understanding my problem:

for file in *
do
    customdate="$(sed -n 2p $file)"
done

for file in * sort by $customdate
do
    #do something here
done

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗恋未遂 2024-12-29 06:34:36

我认为你需要两个循环。第一个列表从文件中读取该日期并构建索引。第二个循环遍历该索引。您可以使用分隔符再次拆分索引,以再次从索引中获取文件名。

index=""
for file in *
do
   customdate="$(head -2 $file | tail -1)"
   index="${index}${customdate},${file}\n"
done

for key in `echo -e ${index} | sort`
do
   customdate=${key/,.*/}
   file=${key/.*,/}
   # PROCESS FILE HERE
done

I think you need two loops. The first list reads that date out of the files and builds an index. and the second loop goes through that index. You can use a delimiter to split the index out again to get the filename out of the index again.

index=""
for file in *
do
   customdate="$(head -2 $file | tail -1)"
   index="${index}${customdate},${file}\n"
done

for key in `echo -e ${index} | sort`
do
   customdate=${key/,.*/}
   file=${key/.*,/}
   # PROCESS FILE HERE
done
酒浓于脸红 2024-12-29 06:34:36

您应该一起执行两个循环,如下所示:

for file in *
do
  customdate = "$(head -2 $file | tail -1)"
  # do something here, e.g. pipe to sorting command, call sorting function, or whatever
done

这会像您一样从文件中读取自定义日期(只是使用稍微不同的命令,主要是因为我不喜欢 sed)。目的是让 $customdate 同时可用,因为 $file 包含正确的名称,因此您可以在排序中使用两者。

You should just do the two loops together, something like this:

for file in *
do
  customdate = "$(head -2 $file | tail -1)"
  # do something here, e.g. pipe to sorting command, call sorting function, or whatever
done

This reads the custom date from the file like you did (just using slightly different commands, mainly because I suck at sed). The intent is that you have the $customdate available at the same time as $file contains the proper name, so you can use both in the sorting.

帅气称霸 2024-12-29 06:34:36

从 zsh 4.3.9dev2 开始,有一个用于自定义的 glob 限定符排序:

oeo+ 是特殊情况;它们各自后面跟着 shell 代码,分别按照 e glob 限定符和 + glob 限定符进行分隔(参见上文)。针对每个匹配的文件执行代码,参数 REPLY 设置为输入时的文件名称,并将 globsort 附加到 zsh_eval_context。代码应该以某种方式修改参数REPLY。返回时,使用参数的值而不是文件名作为要排序的字符串。

您可以使用此限定符来构建文件名列表。这是一个按行的全部内容排序的基本版本:

for file in *(oe\''REPLY=$({ read -r REPLY && IFS= read -r REPLY; } <$REPLY)'\'); do …

如果您的日期仅包含行的一部分或采用某种奇怪的格式,请对其进行解析。例如,如果您有欧洲风格的日期(日/月/年):

for file in *(oe\''REPLY=$({ read -r REPLY && IFS=/ read -r d m y &&
                             REPLY=$((y*10000+m*100+d)); } <$REPLY)'\'); do …

在任何 shell 中,您可以构建一个前面加上日期的名称列表,对该列表进行排序,然后剪切出日期。我假设所有文件名都不包含换行符,并且所有日期都不包含任何 | 字符。

names=
IFS='
'
for file in *; do
  { read -r line; read -r line; } <"$file"
  # If needed, process $line into something that is to be sorted lexicographically.
  names="$names
  $line|$file"
done
names=$(echo "$names" | sort)
set -f
for file in $names; do
  set +f
  file=${file#*|}
  …
done

Since zsh 4.3.9dev2, there is a glob qualifier for custom sorting:

oe and o+ are special cases; they are each followed by shell code, delimited as for the e glob qualifier and the + glob qualifier respectively (see above). The code is executed for each matched file with the parameter REPLY set to the name of the file on entry and globsort appended to zsh_eval_context. The code should modify the parameter REPLY in some fashion. On return, the value of the parameter is used instead of the file name as the string on which to sort.

You can use this qualifier to build your file name list. Here's a basic version that sorts by the full contents of the line:

for file in *(oe\''REPLY=$({ read -r REPLY && IFS= read -r REPLY; } <$REPLY)'\'); do …

If your date consists only of part of the line or is in some oddball format, parse it around. For example, if you have a European-style date (day/month/year):

for file in *(oe\''REPLY=$({ read -r REPLY && IFS=/ read -r d m y &&
                             REPLY=$((y*10000+m*100+d)); } <$REPLY)'\'); do …

In any shell, you can build a list of names with the date prepended, sort that list, then cut out the dates. I'll assume none of the file names contains a newline character and none of the dates contain any | character.

names=
IFS='
'
for file in *; do
  { read -r line; read -r line; } <"$file"
  # If needed, process $line into something that is to be sorted lexicographically.
  names="$names
  $line|$file"
done
names=$(echo "$names" | sort)
set -f
for file in $names; do
  set +f
  file=${file#*|}
  …
done
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文