male_nominee.txt
female_nominee.txt
性別に応じて、次のファイルを2つのファイルに分割するシェルスクリプトを作成します。ファイルが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 回答を使用すると、データ型を変更できます。
年齢|名前|性別|高い|重量|…
|
しかし、彼らは2番目と性別の間にスペースがある線を無視します。
強く打つ
#!/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
。バラよりシェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか? ただし、シェルループを使用してテキストを処理することの欠点の1つは、ループが繰り返されるたびに外部ユーティリティを呼び出すことが多いことです。この例ではそうではありません。 - また、人為的に何かをするように指定された場合殻に完全に入っていて、 その後、宿題の規則に従う必要があります。
- これはファイルのスペースにもっと寛大ですが、セックスの後に追加データを許可しません。
- 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
また、スクリプトにはいくつかの問題があります。
ファイルに両方の条件が含まれており、両方の条件が毎回通過するため、あなたのステートメントは代わりにif
grepです。names.txt
line
Male
Female
すべての行で変数に割り当てる必要はなく、変数は使用されません。あなたはこれを行うことができますif echo "$line" | grep -q 'Male'; then
if / elseのように、2つの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)
する:
- 「男性」の全検索
names.txt
- 出力(「男性を含むすべての行」)を返し、それを変数に割り当てます。
i
- もし分配する成功した場合(常に成功する必要がある場合)、ifの内容を実行します。
1行ずつ読みながら、その行だけを確認したい場合があります。
使用できますif echo "$line" | grep -q "Male"
(またはPOSIXで定義されていない-qを回避するには、出力にリダイレクトされます/dev/null
)。
これは行全体で「Male」を検索するため、ファイルに「AMalek」という人が含まれていると失敗する可能性があります。
読み込むのではなく、1行ずつ読み込むときは、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