استبدال مسار DOS إلى UNIX داخل الملف
سؤال
لدي ملف يحتوي على هذا النوع من المسارات:
C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c
وأريد الحصول على الملف التالي:
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
لاحظ أنه لا ينبغي تعديل المسار غير المطابق.
أعرف كيفية القيام بذلك باستخدام sed لعدد ثابت من subdir، ولكن الرقم المتغير يسبب لي مشكلة.في الواقع، أود أن استخدام الكثير s/x/y/
التعبيرات (ما يصل إلى أقصى عمق ...ليست أنيقة جدًا).
قد يكون الأمر محرجًا، لكن هذا النوع من السحر يتجاوز مهاراتي.
لمعلوماتك، أحتاج إلى هذه الخدعة لتصحيح بعض ملفات gcov الثنائية على منصة cygwin.
أنا أتعامل مع الملفات الثنائية.لذلك، قد يكون لدي النوع التالي من البيانات:
bindata\bindata%bindataC:\good\foo.c
والتي ينبغي ترجمتها على النحو التالي:
bindata\bindata%bindataC:/good/foo.c
الأول \
لا يجب ترجمتها، رغم أنها على نفس الخط.
ومع ذلك، لقد قمت للتو بفحص حسابي .gcno
الملفات أثناء تحرير هذا النص ويبدو أن جميع المسارات محاطة بالأصفار، لذا يجب أن تكون معظم الإجابات أدناه مناسبة.
المحلول
sed -e '/^C:\\good/ s/\\/\//g' input_file.txt
نصائح أخرى
أنصحك بالنظر في cygpath
الأداة المساعدة، التي تحول أسماء المسارات من تنسيق إلى آخر.على سبيل المثال على جهازي:
$ cygpath `pwd`
/home/jericson
$ cygpath -w `pwd`
D:\root\home\jericson
$ cygpath -m `pwd`
D:/root/home/jericson
إليك تطبيق Perl لما طلبته:
$ echo 'C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c' | perl -pe 's|\\|/|g if /good/'
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
إنه يعمل مباشرة مع السلسلة، لذلك سيعمل في أي مكان.يمكنك الجمع بينه وبين cygpath
, ، ولكنه يعمل فقط على الأجهزة التي لها هذا المسار:
perl -pe '$_ = `cygpath -m $_` if /good/'
(نظرًا لعدم وجود C:\good على جهازي، أحصل على إخراج مثل C:goodfoo.c
.إذا كنت تستخدم مسارًا حقيقيًا على جهازك، فيجب أن يعمل بشكل صحيح.)
تريد الاستبدال"/
"للجميع"\
"ولكن فقط على الأسطر التي تطابق مسار الدليل الجيد.سيسمح لك كل من sed و awk بالقيام بذلك من خلال وجود تعبير LHS (مطابق) يختار فقط الخطوط ذات المسار الصحيح.
سيبدو البرنامج النصي sed التافه للقيام بذلك كما يلي:
/[Cc]:\\good/ s/\\/\//g
للحصول على ملف:
c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar
سوف تحصل على الإخراج أدناه:
c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar
إليك كيف سأفعل ذلك في awk:
# fixpaths.awk
/C:\\good/ {
gsub(/\\/,"/",$1);
print $1 >> outfile;
}
ثم قم بتشغيله باستخدام الأمر:
awk -f fixpaths.awk paths.txt; mv outfile paths.txt
أو ببعض المساعدة من Good ol 'Bash:
#!/bin/bash
cat file | while read LINE
do
if <bad_condition>
then
echo "$LINE" >> newfile
else
echo "$LINE" | sed -e "s/\\/\//g" >> newfile
fi
done
جرب هذا
sed -re '/\\good\\/ s/\\/\//g' temp.txt
أو هذا
awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt