단어를 기준으로 파일을 두 개의 파일로 분할

단어를 기준으로 파일을 두 개의 파일로 분할

male_nominee.txtfemale_nominee.txt성별에 따라 다음 파일을 두 개의 파일로 분할하는 쉘 스크립트를 작성하십시오 . 파일이 male_nominee.txt이미 female_nominee.txt존재하는 경우 내용을 추가합니다.

female_nominee.txt및의 내용을 표시합니다.male_nominee.txt

names.txt

23|Arjun|Male

24|Akshara|Female

17|Aman|Male

19|Simran|Female

내 코드:

while IFS= read -r line;
do
    if i=$(grep "Male" names.txt)
    then
        echo "$line" >> male_nominee.txt
    fi
    if j=$(grep "Female" names.txt)
    then
        echo "$line" >> female_nominee.txt
    fi
done < "names.txt"
ls
cat male_nominee.txt
cat female_nominee.txt

names.txt내 출력에는 두 파일의 내용이 모두 있습니다. 누구든지 이 문제를 해결하도록 도와줄 수 있나요?

답변1

또한 몇 가지 변경 사항이 있습니다.

awk — 단일 패스

awk -F'|' '
   $3 == "Male"   { print >> "male_nominee.txt"   }
   $3 == "Female" { print >> "female_nominee.txt" }
          ' names.txt

~처럼jesse_b의 답변, 그러나 파일을 한 번만 읽고 awk 스크립트 내에서 I/O 리디렉션을 수행합니다. 이러한 awk 답변을 사용하면 데이터 형식을 수정할 수 있습니다.

나이|이름|성별|높은|무게|…

|그러나 그들은 두 번째와 성별 사이에 공백이 있는 선을 무시합니다.

세게 때리다

#!/bin/bash
while read line
do
        if [[ $line =~ Male$ ]]
        then
                printf '%s\n' "$line" >> male_nominee.txt
        fi
        if [[ $line =~ Female$ ]]
        then
                printf '%s\n' "$line" >> female_nominee.txt
        fi
done < names.txt

나는 이것이 당신이 원하는 것이라고 생각합니다. 각 줄을 쉘로 읽고 성별이 남성인지 여성인지 테스트합니다.

  • 일반적으로 Jesse의 말이 옳습니다. 일반적으로 이를 피해야 합니다  while read. 바라보다쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?  그러나 쉘 루프를 사용하여 텍스트를 처리할 때의 단점 중 하나는 루프가 반복될 때마다 외부 유틸리티를 호출하는 경우가 많다는 것입니다. 이 예제에서는 그렇지 않습니다.
  • 또한, 인위적으로 어떤 일을 하도록 지정받은 경우껍질에 완전히 들어 있고, 그런 다음 숙제 규칙을 따라야 합니다.
  • 이는 파일의 공백에 더 관대하지만 섹스 후에 추가 데이터를 허용하지 않습니다.
  • Bash에서는 =~문자열을 정규식과 비교합니다. 정규식에서 는 $끝을 의미하므로 $line =~ Male$ 다음을 확인하세요.$line 에 의해. . 마치다 Male. $line =~ Male(를 데려오지 않고 ) 그냥 말하면 $말레피센트라는 여자는 남자로 간주됩니다.
  • \데이터의 백슬래시()가 걱정된다면 read -r그냥 read.
  • 이 경우에는 중요하지 않을 수 있지만(모든 줄이 숫자로 시작하는 경우) 일반적 printf으로 echo.

POSIX 쉘

#!/bin/sh
while read line
do
        case "$line" in
            (*Male)
                printf '%s\n' "$line" >> male_nominee.txt
                ;;
            (*Female)
                printf '%s\n' "$line" >> female_nominee.txt
                ;;
        esac
done < names.txt
  • 이는 bash 버전보다 이식성이 더 뛰어납니다.
  • case셸의 패턴에 대해 문자열을 테스트하는 전통적인 방법입니다. 정규식 대신 파일 이름 일치(예: glob) 패턴을 사용합니다.
  • *전역 패턴이 일치해야 하므로 성별 값 앞에 를 넣어야 합니다 . Male(none  )을 선택하면 *해당 항목만 일치합니다.오직단어 Male (즉, 나이와 이름이 없음). 반면에 이는 끝에 마크업을 추가할 필요가 없음을 의미합니다.

답변2

"Fmale_nominee.txt 및 male_nominee.txt의 내용 표시" 요구 사항은 약간 불분명하며 IMO는 스크립트에 자리가 없지만 어쨌든 포함하겠습니다. 파일을 읽기 위해 일반적으로 while read 루프를 사용하는 것을 피해야 하며, 이는 구분된 파일이므로 awk를 사용하여 쉽게 관리할 수 있습니다.

#!/usr/bin/env sh 

infile=./names.txt

awk -F\| '$3 == "Male"' "$infile" >> male_nominee.txt
awk -F\| '$3 == "Female"' "$infile" >> female_nominee.txt

cat male_nominee.txt female_nominee.txt

또한 스크립트에 몇 가지 문제가 있습니다.

파일에 두 조건이 모두 포함되어 있고 두 조건이 매번 통과하기 때문에 귀하의 명령문은 대신 ifgrep입니다 .names.txtlineMaleFemale

모든 줄에서 변수에 할당할 필요가 없으며 변수는 사용되지 않습니다. 당신은 이것을 할 수 있습니다if echo "$line" | grep -q 'Male'; then

if/else처럼 두 개의 if 문이 필요하지 않습니다.

if echo "$line" | grep -q 'Male'; then
  echo "$line" >>male_nominee.txt
else
  echo "$line" >>female_nominee.txt
fi

답변3

귀하의 질문은 진술입니다

if i=$(grep "Male" names.txt)

할 것이다:

  1. "남성"에 대한 전체 검색names.txt
  2. 출력("남성을 포함하는 모든 줄")을 반환하고 이를 변수에 할당합니다.i
  3. 만약에분배하다성공하면(항상 성공해야 함) if의 내용을 실행합니다.

한 줄씩 읽으면서 해당 줄만 확인하고 싶을 수도 있습니다.

사용할 수 있습니다 if echo "$line" | grep -q "Male"(또는 POSIX에서 정의되지 않은 -q를 피하려면 출력을 로 리디렉션 /dev/null).

이는 전체 줄에서 "Male"을 검색하므로 파일에 "AMalek"이라는 사람이 포함되어 있으면 실패할 수 있습니다.

읽는 대신 한 줄씩 읽을 때 IFS="|" read -r age name gender다음을 사용할 수 있습니다.if [ $var = "value" ];

또 다른 옵션은 grep을 사용하는 것입니다. 이 경우 선행 "|"(특수 문자임에 유의)가 필요하며 줄이 끝납니다.

이 경우 전체 루프를 몇 개의 grep으로 대체할 수 있습니다.

(여자의 실수는 남자의 실수와 똑같습니다)

답변4

다음은 간단한 해결책입니다. grep을 사용하여 필터링하고 ">>"를 사용하여 추가합니다.

grep "Female$" names.txt >> female_nominee.txt
grep "Male$" names.txt >> male_nominee.txt

cat female_nominee.txt
cat male_nominee.txt

관련 정보