如何替换“$0”但保存旧值?

mbi*_*ras 1 command-line grep bash awk

我试图将所有以“m”开头的文件重命名为相同的名称,除了第一个字符(或在本例中为“m”)被删除。

我的策略是:

  1. 列出所有文件,使用 ls
  2. 过滤我想要的那些 egrep
  3. 在我想要的字符串旁边生成我不想要的字符串,用空格分隔awk,例如,mfoo foo
  4. 送入xargsmv mfoo foo

一些问题:

  • 这是一个好策略吗?
  • 什么是更好的?

我被困在第 3 步,下面是我解决问题的方法。

我在以下目录中工作:

$ find .
.
./cat
./mbar
./mbaz
./mfoo
Run Code Online (Sandbox Code Playgroud)

我能够快速获得 1-2:

$ ls | egrep '^m'
mbar
mbaz
mfoo
Run Code Online (Sandbox Code Playgroud)

第 3 步更难。我曾经gsub生成我想要的第二个字符串,但我不确定如何“将它与以空格分隔的原始值粘在一起”:

$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo
Run Code Online (Sandbox Code Playgroud)

第 4 步对我来说很有意义,虽然我不确定如何完成第 3 步,所以我还不能完成它。下面是我认为它应该如何工作的一个例子:

$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz
Run Code Online (Sandbox Code Playgroud)

我想我很接近我只需要找出如何保存旧值并将其打印在 gsubed 值旁边。我试过下面的小例子,但它不起作用:

$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
 input record number 1, file
 source line number 4
Run Code Online (Sandbox Code Playgroud)
  • 如何替换$0但保存旧值?
  • 为什么我收到这个错误?

Ste*_*itt 7

这应该处理整个操作:

for file in m*; do mv "${file}" "${file#m}"; done
Run Code Online (Sandbox Code Playgroud)

在你运行之前,先检查一下

for file in m*; do echo mv "${file}" "${file#m}"; done
Run Code Online (Sandbox Code Playgroud)

这将m*glob 用于第 1 步和第 2 步,然后${file#m}(从 的开头删除“m” ${file})用于第 3 步,最后是第 4 步的循环。

要回答您的 AWK 问题,您可以这样做:

echo mfoo | awk '{ print $0, substr($0, 2) }'
Run Code Online (Sandbox Code Playgroud)

AWK 变量不使用$,仅用于字段;这就是您的错误的来源:AWK 理解$old为“根据 的值编号的字段值old”。如果将命令放在单个块中(假设它们具有相同的模式),也更容易阅读。修复你的脚本给

echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'
Run Code Online (Sandbox Code Playgroud)

  • 分解任务是一个很好的策略,但你需要使用适当的工具(学习所有工具是一项永无止境的任务......)。解析 `ls` 的输出 [不是一个好主意](http://unix.stackexchange.com/q/128985/86440),使用 AWK 进行简单的字符串处理是过度的。 (2认同)