将文件信息移动到另一个文件

将文件信息移动到另一个文件

我有两个文件,current_employee.txt并且former_employee.txt.当员工辞职时,我必须将他们的信息从current_employee.txt移至former_employee.txt。请注意,我想移动一名即将辞职的人的信息。

就像current_employee.txt

name:john
surname:James
salary:3000
department:finance

name:Paul
surname:Perez
salary:5000
department:inventory

name:Abel
surname:Wood
salary:4000
department:inventory

所以我想移动保罗的详细信息......

我尝试使用 cat current_employee.txt >former_employee.txt 但它将所有员工详细信息移至 previous_employee.txt 中。我做了所有的研究,但我不明白我能做什么

答案1

awk -v name=Paul '
    BEGIN { RS=""; FS=":"; ORS="\n\n"; name = tolower(name) }
    tolower($2) == name { print; next }
    { print >(FILENAME ".new") }' current_employee.txt >>former_employee.txt

这会做几件事,在命令行上给出一个名称(此处Paul)。它将把输入文件current_employee.txt视为一组记录,它们之间有一个空行(这就是所做的RS="")。每个此类记录都根据 划分为多个字段:,因此(假设该name行始终位于第一行)$1始终是标签name并且$2始终是员工的名字。

然后,它将输出记录分隔符设置为双换行符,以确保代码输出的每个记录末尾始终有一个空行。它还将查询名称小写,以防查询字符串的大写/小写和数据不能完全相信是正确的(john例如,已经全部小写)。

如果从输入文件读取的当前记录中的小写名称与我们的小写查询字符串相同,则输出整个记录,并且程序使用 跳到下一行输入next

如果当前记录中的名称不是我们要查找的名称,则该记录也会输出,但会输出到一个文件名与输入文件的文件名相同的文件中,并.new在末尾添加。

代码的输出awk附加的>>文件former_employee.txt

这意味着当你运行它时,你会得到类似这样的结果:

$ ls
current_employee.txt
$ cat current_employee.txt
name:john
surname:James
salary:3000
department:finance

name:Paul
surname:Perez
salary:5000
department:inventory

name:Abel
surname:Wood
salary:4000
department:inventory
$ awk -v name=Paul '
    BEGIN { RS=""; FS=":"; ORS="\n\n"; name = tolower(name) }
    tolower($2) == name { print; next }
    { print >(FILENAME ".new") }' current_employee.txt >>former_employee.txt
$ ls
current_employee.txt      current_employee.txt.new  former_employee.txt
$ cat former_employee.txt
name:Paul
surname:Perez
salary:5000
department:inventory

$ cat current_employee.txt.new
name:john
surname:James
salary:3000
department:finance

name:Abel
surname:Wood
salary:4000
department:inventory

然后您可以使用

mv current_employee.txt.new current_employee.txt

用更新的记录替换当前员工的旧记录。


将上述稍微笨拙的命令包装在 shell 脚本中,并给它更多的空气:

#!/bin/sh

for file in current_employee.txt former_employee.txt
do
    if [ -f "$file" ] && cp "$file" "$file-orig"; then
        printf 'Backed up %s as %s-orig\n' "$file" "$file"
    fi
done

awk -v name="$1" '
BEGIN {
    RS = ""
    FS = ":"
    ORS = "\n\n"
    name = tolower(name)
}

tolower($2) == name { print; next }

{ print >(FILENAME ".new") }' current_employee.txt >>former_employee.txt &&
mv current_employee.txt.new current_employee.txt

该脚本将备份current_employee.txt和两个文件former_employee.txt,然后根据作为脚本第一个参数给出的名称更新它们。

您通常会使用这个脚本,例如

$ ./script Paul

答案2

使用 GNU awk 实用程序 v4.1.0 或更高版本以及 inplace 选项来就地编辑文件

# set input n output filenames
if=current_employee.txt
of=former_employee.txt

gawk -F: -i inplace -v n="John" '
  /^name:/&&tolower($2)==tolower(n),!NF{
    print >> OUT;next
  }1
' OUT="$of" "$if"

使用 GNU 行编辑器编辑:

### set input n output filenames
if=current_employee.txt
of=former_employee.txt

### user defined function to make changes
fx() {
  ## unpack arguments
  n=$1

  ## escape any regex chars in name
  for e in \\ \[ ^ \$ . \* /;do
    n=${n//"$e"/\\"$e"}
  done

  ## make name case insensitive
  set -- {a..z}
  for UC in {A..Z}; do
    lc=$1; shift
    n=${n//[$lc$UC]/"[$lc$UC]"}
  done

  ## define the block which contains the name e.g., john
  block="?^name:${n}\$?;/^\$/"

  ## invoke ed editor to make changes
  ed -s "$if" <<eof
# add a dummy line to eof
a

.
# append block to former employee file
${block}W $of
# delete block from current employee file
${block}d
# take away the dummy line added
\$d
# save n quit from the current employee file
wq
eof
}

## and now invoke fx to make the changes in files
fx 'john'
### end

现在检查现任和前任员工文本文件以查看更改。

相关内容