الحفاظ الرائدة المساحة البيضاء أثناء القراءة >> كتابة سطر الملف عن طريق خط في باش

StackOverflow https://stackoverflow.com/questions/1648055

  •  22-07-2019
  •  | 
  •  

سؤال

وأنا أحاول أن يتكرر خلال دليل من ملفات نصية والجمع بينهما في وثيقة واحدة. هذا وتعمل كبرى، ولكن ملفات نصية تحتوي على مقتطفات الشفرة، وجميع من التنسيق بلدي هو الحصول على انهار على اليسار. تجريد كل المسافات الرائدة على الخط.

#!/bin/sh
OUTPUT="../best_practices.textile"
FILES="../best-practices/*.textile"
for f in "$FILES"
do
  echo "Processing $f file..."
  echo "">$OUTPUT

  cat $f | while read line; do 
      echo "$line">>$OUTPUT
  done
  echo >>$OUTPUT
  echo >>$OUTPUT
done

وأنا المسلم مستجد باش، ولكن بعد البحث العالية والمنخفضة لم أتمكن من العثور على حل مناسب. يبدو BASH يكره المساحة البيضاء مما يؤدي بشكل عام.

هل كانت مفيدة؟

المحلول

وبدلا من:

cat $f | while read line; do 
    echo "$line">>$OUTPUT
done

هل هذا:

cat $f >>$OUTPUT

(إذا كان هناك سبب ما عليك القيام به الأشياء سطرا سطرا انه سيكون من المناسب إدراج ذلك في السؤال).

نصائح أخرى

وكما أشار آخرون، وذلك باستخدام القط أو AWK بدلا من حلقة للقراءة الصدى هو وسيلة أفضل بكثير للقيام بذلك - يتجنب مشكلة تقليم بيضاء (واثنين آخرين لم تكن قد عثر عليها)، يعمل بشكل أسرع، وعلى الأقل مع القط، هو رمز ببساطة أكثر نظافة. ومع ذلك، أود أن أغتنم طعنة في الحصول على حلقة للقراءة صدى للعمل مباشرة.

أولا، مشكلة تقليم بيضاء: الأمر قراءة الديكورات تلقائيا الرئيسي وراء بيضاء. وهذا يمكن أن تكون ثابتة عن طريق تغيير تعريفه من المسافات عن طريق تعيين متغير IFS إلى فارغة. أيضا، قراءة يفترض أن مائل في نهاية السطر يعني السطر التالي هو استمرار، ويجب أن تقسم إلى جانب هذا واحد؛ لإصلاح هذا، استخدم فيها (الخام) علم -r. المشكلة الثالثة هنا هي أن العديد من تطبيقات صدى تفسير أحرف في السلسلة (على سبيل المثال، فإنها قد تتحول \ ن إلى السطر الفعلي)؛ لإصلاح هذا، استخدم printf بدلا من ذلك. وأخيرا، فقط كقاعدة النظافة البرمجة العامة، يجب عدم استخدام القط عندما لا تحتاج في الواقع إلى؛ استخدام مدخلات إعادة توجيه بدلا من ذلك. مع هذه التغييرات، وحلقة داخلية تبدو مثل هذا:

while IFS='' read -r line; do 
  printf "%s\n" "$line">>$OUTPUT
done <$f

و... هناك أيضا بضعة مشاكل أخرى مع النصي المحيطة: الخط الذي يحاول تحديد FILES كقائمة من الملفات. نسيج المتاحة لديها يقتبس من حوله، وهذا يعني أنه لم يحصل سعت إلى قائمة الفعلية للملفات . أفضل طريقة للقيام بذلك هو استخدام صفيف:

FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"

(ويجب أن تكون كافة تواجدات $ و في مزدوجة نقلت في حالة أي من أسماء ومسافات أو أحرف مضحك أخرى فيها - يجب أن تفعله حقا هذا مع $ OUTPUT كذلك، على الرغم منذ ذلك انها تعرف في البرنامج النصي انها في الواقع آمنة لمغادرة خارج).

وأخيرا، هناك echo "">$OUTPUT بالقرب من أعلى للملفات حلقة تنته أن يحدث لمحو ملف الإخراج كل مرة من خلال (أي في النهاية، فإنه يحتوي فقط على الملف. نسيج الماضي)؛ هذا يحتاج إلى أن انتقلت إلى قبل الحلقة. أنا لست متأكدا مما إذا كان القصد هنا لوضع سطر فارغ واحد في بداية الملف، أو ثلاثة أسطر فارغة بين الملفات (واحدة في بداية واثنان في النهاية)، لذلك لست متأكدا بالضبط ما والبديل المناسب هو. على أي حال، وهنا ما يمكن أن تصل إليه بعد تحديد كل هذه المشاكل:

#!/bin/sh
OUTPUT="../best_practices.textile"
FILES=(../best-practices/*.textile)

: >"$OUTPUT"
for f in "${FILES[@]}"
do
  echo "Processing $f file..."
  echo >>"$OUTPUT"

  while IFS='' read -r line; do 
    printf "%s\n" "$line">>"$OUTPUT"
  done <"$f"

  echo >>"$OUTPUT"
  echo >>"$OUTPUT"
done

وهذا هو وسيلة مكلفة أكثر مما ينبغي الجمع بين الملفات.

cat ../best-practices/*.textile >  ../best_practices.textile

وإذا كنت ترغب في إضافة فارغة (السطر الجديد) إلى كل ملف كما لسلسلة، واستخدام AWK

awk 'FNR==1{print "">"out.txt"}{print > "out.txt" }' *.textile

وOR

awk 'FNR==1{print ""}{print}' file* > out.txt

وهذا يسمح لك لنثر أسطر جديدة بين كل ملف الإدخال كما فعلت في النص الأصلي:

for f in $FILES; do echo -ne '\n\n' | cat "$f" -; done > $OUTPUT

لاحظ أن $FILES هو غير المدرجة لهذا العمل (وإلا أسطر إضافية تظهر مرة واحدة فقط في نهاية كل المخرجات)، ولكن يجب أن تكون نقلت $f لحماية المساحات في أسماء الملفات، إذا كانت موجودة.

scroll top