如何在csh中一行代码中写foreach循环?

12
有时我在csh中使用相同的foreach操作,但是针对不同的目标文件。
如果我可以在一行命令中使用foreach命令,我就可以轻松地替换目标文件名以重复该过程。(我通常使用 `find . -name ...` 来查找目标文件)
为了回答这个问题,假设我想把所有 *.txt 文件连接起来。
$ foreach i (*.txt)
foreach? cat $i
foreach? end

我读了https://unix.stackexchange.com/questions/32873/running-a-full-foreach-command,并尝试过。

alias disp 'echo "foreach i (*.txt)"; echo "cat "\$"i"; echo "end"; | /bin/csh'
当我输入disp时,它会显示Invalid null command
如果我可以在一行中完成,我可以执行!foreach:gs/\.c\>/.h/(用.h替换.c)。 我应该如何做?
6个回答

15

这个方法对我很有效:

printf 'foreach f ( 1 2 3 )\n echo $f \n end' | tcsh

哇,这是一个长时间未回答的问题,但你的回答解决了它!谢谢! - Chan Kim
1
printf 'foreach f ( 1 2 3 )\n echo $f \n end \n' | tcsh - humility
printf和echo相比有什么优势吗? - Kevin

4

在tcsh中,没有一种简单的方法可以在一行内完成foreach操作。

但是,通过使用别名,您可以得到非常接近您问题的东西。

alias disp 'foreach i (*.txt)\
  cat $i\
end'

您可以在终端中调用 disp

如果您想将结果直接导入管道,则使用 echo `disp` | grep foobar

有时,在进一步处理之前,我们需要首先保存结果:set foo=`disp`


我喜欢这个答案胜过那个涉及启动子进程的答案。想要一行完成的最常见原因是作为别名使用,而这个解决了这个问题。 - All The Rage
这种方法的一个缺点是历史记录会混乱。它看起来像:disp\n cat $i\n end\n - All The Rage
这真是太棒了! 我的使用情况是修改当前的shell,这非常完美。 我没有@AllTheRage提到的“混乱的历史记录”。 谢谢! - dado

0

使用bash -c:

$ bash -c 'for i in *.txt; do cat $i; done'


0
别名可能作为一种解决方法,但可能会很麻烦且有限。最好创建一个脚本或FIFO文件。这里有一个文件的示例。
echo '\
# Functions\
alias function '\''( set argv = ( \\\!* ) ; source ~/.cshfuncs )'\' >> ~/.cshrc
echo 'switch ("$1")\
  case 'disp':\
    shift\
    foreach i (*.txt)\
      cat "$i"\
    end\
    exit\
  default:\
    echo "Function $1 not set."\
    exit\
endsw' > ~/.cshfuncs

这是一个FIFO的例子。
mkfifo ~/fifo
echo 'foreach i (*.txt)\
cat "$i"\
end' > ~/fifo & ( source ~/fifo )

-1
对于您的第一个问题,我不知道如何直接在.cshrc文件中编写此内容。
但是我将使用另一种灵活的方式来解决这个问题。
1:编写一个shell脚本: /home/user/disp.sh(或任何您想要的路径)
#/bin/bash
for line in `find . -name "*.c"`; do
echo ""
   cat "$line"
done

或者你只有csh shell:

#/bin/csh
foreach i (*.c)
    echo $i
end
  1. .cshrc 文件中添加新的别名命令

    alias disp /home/user/disp.sh

  2. 重新进入 csh shell(或重新登录)

    csh


针对您的第二个问题,我在同一个disp.sh脚本中完成了它。 < p > < em > 这个例子是用bash shell脚本编写的。
#/bin/bash
usage() { echo "Usage: $0 [-d <depth>] [-e <extension>]" 1>&2; exit 1; }
while getopts ":d:e:" o; do
    case "${o}" in
        d)
            d=${OPTARG}
            ;;
        e)
            e=${OPTARG}
            ;;
        *)
            usage
            ;;
    esac
done
shift $((OPTIND-1))
if [ -z "${d}" ] || [ -z "${e}" ]; then
    usage
fi

for line in `find . -maxdepth ${d} -name "*.${e}"`; do
echo ""
   cat "$line"
done

你可以直接输入 disp -d 1 -e c 来查找当前路径下所有的 .c 文件。 (-d 表示从当前路径开始的文件深度,-e 表示文件扩展名)

嗨,我觉得你没有理解问题。我想在单行中使用整个foreach命令,这样我就可以轻松地替换其中的一部分并再次运行该命令。在bash中,我可以简单地使用for i in 1 2 3; do echo $i; done - Chan Kim

-1

我尝试寻找答案,但似乎没有办法。只需通过更改 shell 使用 bash。

% bash

$ for f in *txt; do echo $f; done

$ exit

%


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接