سؤال

اسمحوا لي أن أقدم هذا بالقول إنني هواة كاملة عندما يتعلق الأمر بـ Regex وبدأت فقط قبل بضعة أيام. أحاول حل مشكلة تنسيق ملف وضغط على عقبة مع نوع معين من البيانات. ملف الإدخال منظم مثل هذا:

Two words,Word,Word,Word,"Number, number"

ما يجب علي فعله هو تنسيقه مثل هذا ...

"Two words","Word",Word","Word","Number, number"

لقد كان لدي نمط regex من

s/,/","/g

العمل ، باستثناء أنه يحل محل الفاصلة في الرقم المقتبس بالفعل ، قسم الأرقام ، والذي يتسبب في فصل الحقل وكسر الملف. في الأساس ، أحتاج إلى تعديل نمطتي لاستبدال فاصلة بـ "،" [اقتباس اقتباس فاصلة] ، ولكن فقط عندما لا يتم اتباع الفاصلة بمساحة. لاحظ أن الحقول الأخرى لن يكون لها مساحة تتبع الفاصلة ، فقط قائمة الأرقام المحددة.

تمكنت من الكتابة

s/,[A-Za-z0-9]/","/g

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

s/(,)[A-Za-z0-9]\b

يجب أن تعمل ، لكنها لا.

أي شخص لديه فكرة؟

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

المحلول

s/,([^ ])/","$1/ سوف يتطابق مع ","متبوعًا بـ" غير مسافة غير متوفرة "، الاستيلاء على الفضاء غير المتفوق ، ثم استبدال كل شيء بالجزء الذي تم التقاطه.

اعتمادًا على محرك Regex الذي تستخدمه ، قد تكتب \1 أو أشياء أخرى بدلاً من $1.

إذا كنت تستخدم Perl أو يمكنك الوصول إلى محرك Regex مع Lookahead السلبي ، s/,(?! )/","/ (أ ","لا تتبعها مساحة) تعمل.

يبدو أن إدخالك يشبه CSV ، وإذا كان الأمر كذلك ، فمن الأفضل أن تكون أفضل حالًا مع محلل CSV حقيقي بدلاً من regexes. هناك الكثير من حالات الزاوية الفردية الأخرى للقلق.

نصائح أخرى

كانت تجربتي هي أن هذا ليس استخدامًا كبيرًا للأناقة. كما قيل سابقًا ، يتم التعامل مع ملفات CSV بشكل أفضل من قبل محلات CSV الحقيقية. لم تضع علامة على لغة ، لذلك من الصعب معرفة ذلك ، لكن في Perl ، أستخدم Text :: CSV_XS أو DBD :: CSV (السماح لي SQL بالوصول إلى ملف CSV كما لو كان جدولًا ، بالطبع ، يستخدم النص :: csv_xs تحت الأغطية). أبسط بكثير من التدحرج الخاص بي ، وأكثر قوة بكثير من استخدام regexes.

هذا السؤال مشابه لـ: استبدال الأنماط الموجودة داخل المحددات باستخدام مكالمة تعبير منتظمة.

هذا يمكن أن يعمل:

s/"([^"]*)"|([^",]+)/"$1$2"/g

يبدو أنك تستخدم SED.

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

من خلال SED ، سيكون الأمر الخاص بك هو:

  sed 's/[ \"]*,[ \"]*/\", \"/g'

لاحظ أنه لا يزال يتعين عليك وضع Doublequotes في بداية ونهاية السلسلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top