파일 정보를 다른 파일로 이동

파일 정보를 다른 파일로 이동

current_employee.txt두 개의 파일 이 있고 직원이 사직하면 해당 정보를 에서 로 former_employee.txt옮겨야 합니다 . 퇴사하시는 분의 정보를 옮기고 싶은 점 양해 부탁드립니다.current_employee.txtformer_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

그래서 Paul의 세부사항을 옮기고 싶습니다...

cat current_employee.txt >former_employee.txt를 사용해 보았지만 모든 직원 세부 정보가 이전_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

현재 직원의 이전 기록을 업데이트된 기록으로 바꿉니다.


위의 약간 서투른 명령을 쉘 스크립트로 감싸서 좀 더 활기차게 만드십시오.

#!/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

이제 현재 및 이전 직원 텍스트 파일을 확인하여 변경 사항을 확인하십시오.

관련 정보