ගොනුවක අවසානයට නව රේඛාවක් එකතු කරන්නේ කෙසේද?


209

අනුවාද පාලන පද්ධති භාවිතා කිරීම වෙනස පවසන විට ශබ්දය නිසා මා කෝපයට පත් No newline at end of fileවේ.

ඉතින් මම කල්පනා කළා: එම පණිවිඩ ඉවත් කිරීම සඳහා ගොනුවක් අවසානයේ නව රේඛාවක් එකතු කරන්නේ කෙසේද?


1
එසේම බලන්න / q / 10082204/155090
RubyT TuesdayDONO

1
සියලු ලිපිගොනු පුනරාවර්තව සනීපාරක්ෂාව කරන පහළින් හොඳ විසඳුමක්. @Patrick Oscity විසින් පිළිතුර
Qwerty


ඉදිරියට යමින්, ඔබට සහ ඔබේ සහකරුවන්ට පිරිසිදුව තබා ගැනීමට භාවිතා කළ හැකි නව රේඛාවක් ඇති බව සහතික කිරීමට පෙළ සංස්කාරකවරුන්ට බොහෝ විට විකල්ප ඇත.
නික් ටී

Answers:


52

ව්‍යාපෘතියක් පුනරාවර්තනව සනීපාරක්ෂාව සඳහා මම මෙම ඔන්ලයින් භාවිතා කරමි:

git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done

පැහැදිලි කිරීම:

  • git ls-files -zගබඩාවේ ගොනු ලැයිස්තුගත කරයි. සමහර පරාමිතීන් ලෙස විකල්ප රටාවක් ගත යුතු අතර සමහර මෙහෙයුම් වලදී ඔබට සමහර ගොනු / නාමාවලි වලට පමණක් සීමා කිරීමට අවශ්‍ය නම් එය ප්‍රයෝජනවත් වේ. විකල්පයක් ලෙස, find -print0 ...බලපෑමට ලක්වූ ලිපිගොනු ලැයිස්තුගත කිරීම සඳහා ඔබට ඒ හා සමාන වැඩසටහන් භාවිතා කළ හැකිය - එය NULසීමා කළ ප්‍රවේශයන් විමෝචනය කරන බවට වග බලා ගන්න .

  • while IFS= read -rd '' f; do ... done වයිට්ස්පේස් සහ / හෝ නව රේඛා ඇතුළත් ගොනු නාමයන් ආරක්ෂිතව හසුරුවමින් ඇතුළත් කිරීම් හරහා නැවත පැමිණේ.

  • tail -c1 < "$f" ගොනුවකින් අවසන් වරහන කියවයි.

  • read -r _ පසුපසින් සිටින නව රේඛාවක් අස්ථානගත වී ඇත්නම්, නොසරෝ පිටවීමේ තත්වයක් සමඟ පිටවීම.

  • || echo >> "$f" පෙර විධානයෙහි පිටවීමේ තත්වය nonzero නම් ගොනුවට නව රේඛාවක් එකතු කරයි.


ඔබේ ලිපිගොනු වල උප කුලකයක් සනීපාරක්ෂාව කිරීමට අවශ්‍ය නම් ඔබට මෙයද කළ හැකිය:find -name \*.java | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
පර් ලුන්ඩ්බර්ග්

@ ස්ටෙෆාන් චැසෙලාස් හොඳ යෝජනා, මෙය මගේ පිළිතුරට ඇතුළත් කිරීමට උත්සාහ කරනු ඇත.
පැට්‍රික් ඔස්සිටි

ErPerLundberg ඔබට git ls-filesඅනුවාද පාලනයේ ලුහුබැඳ නැති ගොනු සංස්කරණය කිරීමෙන් තවමත් ඔබව ගලවා ගන්නා රටාවක් සම්මත කළ හැකිය .
පැට්‍රික් ඔස්සිටි

@ ස්ටෙෆාන් IFS= චැසෙලාස් බෙදුම්කරු සැකසීමට එකතු කිරීම අවට ඇති අවකාශය ආරක්ෂා කිරීමට හොඳය. අහෝසි කරන ලද ඇතුළත් කිරීම් අදාළ වන්නේ ඔබ සතුව නව රේඛාවක් සහිත ලිපිගොනු හෝ නාමාවලි තිබේ නම්, එය බොහෝ දුරට ලබා ගත හැකි යැයි පෙනේ, නමුත් සාමාන්‍ය නඩුව හැසිරවීමට වඩාත් නිවැරදි ක්‍රමය නම්, මම එකඟ වෙමි. කුඩා අවවාදයක් ලෙස: -dවිකල්පය readPOSIX sh හි නොමැත.
පැට්‍රික් ඔස්සිටි

ඔව්, ඒ නිසා මගේ zsh / bash . tail -n1 < "$f"ආරම්භ වන ගොනු නාමයන් සමඟ ඇති ගැටළු මඟහරවා ගැනීම සඳහා මගේ භාවිතයද බලන්න -( tail -n1 -- "$f"හැඳින්වෙන ගොනුව සඳහා ක්‍රියා නොකරයි -). පිළිතුර දැන් zsh / bash විශේෂිත බව ඔබට පැහැදිලි කිරීමට අවශ්‍ය විය හැකිය.
ස්ටෙෆාන් චසෙලාස්

223

මෙන්න ඔබ යන්න :

sed -i -e '$a\' file

OS X සඳහා විකල්පයක් ලෙස sed:

sed -i '' -e '$a\' file

මෙය \nගොනුවේ අවසානයේ එකතු කරන්නේ එය දැනටමත් නව රේඛාවකින් අවසන් නොවන්නේ නම් පමණි . එබැවින් ඔබ එය දෙවරක් ධාවනය කරන්නේ නම්, එය තවත් නව රේඛාවක් එක් නොකරනු ඇත:

$ cd "$(mktemp -d)"
$ printf foo > test.txt
$ sed -e '$a\' test.txt > test-with-eol.txt
$ diff test*
1c1
< foo
\ No newline at end of file
---
> foo
$ echo $?
1
$ sed -e '$a\' test-with-eol.txt > test-still-with-one-eol.txt
$ diff test-with-eol.txt test-still-with-one-eol.txt
$ echo $?
0

1
wjwd: සිට man sed: $ Match the last line.නමුත් සමහර විට එය ක්‍රියාත්මක වන්නේ අහම්බෙන් පමණි. ඔබේ විසඳුම ද ක්රියා කරයි.
l0b0

1
ඔබේ විසඳුම වඩාත් අලංකාරයි, මම එය පරීක්ෂා කර කැප කර ඇත්තෙමි , නමුත් එය ක්‍රියාත්මක වන්නේ කෙසේද? නම් $පසුගිය මාර්ගය තරග, ඇයි එය කරන වැලක් තවත් නව පේළියකට යොමු කිරීමේ අක්ෂරය එකතු කරන්නේ මේ වන විටත් එය නව පේළියකට යොමු කිරීමේ අක්ෂරය අඩංගු?
l0b0

30
යන්නෙහි වෙනස් අර්ථ දෙකක් තිබේ $. පෝරමය වැනි රීජෙක්ස් එකක /<regex>/එයට සුපුරුදු “රේඛාවේ ගැලපීම් අවසානය” යන අර්ථය ඇත. එසේ නොමැතිනම්, ලිපිනයක් ලෙස භාවිතා කරන sed විසින් එයට විශේෂ “ගොනුවේ අවසාන පේළිය” අර්ථය ලබා දෙයි. කේතය ක්‍රියාත්මක වන්නේ පෙරනිමියෙන් sed දැනටමත් එහි නොමැති නම් එහි ප්‍රතිදානයට නව රේඛාවක් එකතු කරන බැවිනි. "$ A \" කේතය "ගොනුවේ අවසාන පේළියට ගැලපෙන අතර එයට කිසිවක් එකතු නොකරන්න" යනුවෙන් පවසයි. නමුත් ව්‍යංගයෙන්, sed $එය දැනටමත් නොමැති නම් එය සකසන සෑම පේළියකටම (මෙම රේඛාව වැනි) නව රේඛාව එක් කරයි .
jwd

1
අත්පොත සම්බන්ධයෙන්: ඔබ සඳහන් කරන උපුටා ගැනීම "ලිපින" කොටස යටතේ ය. එය ඇතුළත /regex/තැබීමෙන් එයට වෙනස් අර්ථයක් ලැබේ. FreeBSD manpages තව ටිකක් තොරතුරු සහිතයි
jwd

2
ගොනුව දැනටමත් නව රේඛාවකින් අවසන් වී ඇත්නම්, මෙය එය වෙනස් නොකරයි, නමුත් එය නැවත ලිවීම සහ එහි කාලරාමුව යාවත්කාලීන කරයි. එය වැදගත් හෝ නොවිය හැකිය.
කීත් තොම්සන්

42

බලන්න:

$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo

ඒ නිසා echo "" >> noeol-fileඋපක්‍රමය කළ යුතුයි. (නැතහොත් ඔබ අදහස් කළේ මෙම ගොනු හඳුනා ගැනීම සඳහා ඉල්ලා හා ඔවුන් සවි?)

සංස්කරණය ඉවත් කර ""ඇත echo "" >> foo(බලන්න @ යූයිචාවෝගේ අදහස බලන්න) edit2"" නැවත එකතු කරන ලදි ( නමුත් e කීත් තොම්සන් ගේ අදහස බලන්න)


5
මෙම ""අවශ්ය නොවේ, (අවම වශයෙන් bash සඳහා) වන අතර, tail -1 | wc -lඅවසානයේ දී නව රේඛාවක් රහිතව ගොනු සොයා ගැනීමට භාවිතා කළ හැක
yuyichao

5
@yuyichao: ""බැෂ් සඳහා අවශ්‍ය නොවේ, නමුත් echoතර්ක නොමැතිව ආයාචනා කරන විට කිසිවක් මුද්‍රණය නොකරන ක්‍රියාත්මක කිරීම් මම දැක ඇත්තෙමි (මට දැන් සොයාගත හැකි කිසිවෙක් මෙය නොකරයි). echo "" >> noeol-fileබොහෝ විට තරමක් ශක්තිමත් වේ. printf "\n" >> noeol-fileඊටත් වඩා වැඩිය.
කීත් තොම්සන්

2
@KeithThompson, cshගේ echoකිසිදු තර්කයක් සම්මත නොවන විට ප්රතිදානය කිසිවක් දන්නා තැනැත්තා ය. එහෙත්, ඉන්පසුව අප නොවන Bourne-වැනි කටු සහාය කරන්න යනවා නම්, අපි එය කළ යුතු ය echo ''වෙනුවට echo ""ලෙස echo ""ouput ඇත ""<newline>සමග rcහෝ esඋදාහරණයක්.
ස්ටෙෆාන් චසෙලාස්

1
@ ස්ටෙෆාන් චැසෙලාස්: තවද tcsh, වෙනස් cshනොවී, තර්කයකින් තොරව නව රේඛාවක් මුද්‍රණය කරයි $echo_style.
කීත් තොම්සන්

දැනටමත් නව රේඛා ඇති ලිපිගොනු වලට අතිරේක නව රේඛාවක් එක් කිරීමට මෙය හේතු නොවේද?
ආරොන් ෆ්‍රෑන්ක්

16

භාවිතා කරන තවත් විසඳුමක් ed. මෙම විසඳුම අවසාන පේළියට පමණක් බලපාන අතර \nඑය නොමැති නම් පමණි :

ed -s file <<< w

එය අත්‍යවශ්‍යයෙන්ම ස්ක්‍රිප්ට් එකක් හරහා සංස්කරණය කිරීම සඳහා ගොනුව විවෘත කරයි, ස්ක්‍රිප්ට් යනු තනි wවිධානයකි, එය ගොනුව නැවත තැටියට ලියයි. එය පදනම් වී ඇත්තේ ed(1)මිනිසාගේ පිටුවේ ඇති මෙම වාක්‍යය මත ය :

සීමාවන්
       (...)

       පෙළ (ද්විමය නොවන) ගොනුවක් නව අක්ෂරයකින් අවසන් නොවන්නේ නම්,
       ඉන්පසු එය කියවීමට / ලිවීමට එඩ් එක් කරයි. ද්විමය සම්බන්ධයෙන්
       ගොනුව, සංස්කරණය කියවීම / ලිවීම පිළිබඳ නව රේඛාවක් එකතු නොකරයි.

1
මෙය මට නව රේඛාවක් එක් නොකරයි.
ඔල්හෝව්ස්කි

4
මා වෙනුවෙන් වැඩ කරයි; එය "නිව්ලයින් ඇපෙන්ඩ්" පවා මුද්‍රණය කරයි (ආර්ච් ලිනක්ස් හි සංස්කරණ 1.10-1).
ස්ටෙෆාන් මජෙව්ස්කි

14

නොසලකා නව රේඛාවක් එක් කරන්න:

echo >> filename

පයිතන් භාවිතා කිරීමෙන් එකක් එක් කිරීමට පෙර අවසානයේ නව රේඛාවක් තිබේදැයි පරීක්ෂා කිරීමට ක්‍රමයක් මෙන්න:

f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $f

1
මන්දගාමී පයිතන් ආරම්භක වේලාව නිසා මම කිසිම ආකාරයක ලූපයක පයිතන් අනුවාදය භාවිතා නොකරමි. ඇත්ත වශයෙන්ම ඔබට අවශ්‍ය නම් පයිතන් වල ලූපය කළ හැකිය.
කෙවින් කොක්ස්

3
පයිතන් සඳහා ආරම්භක වේලාව තත්පර 0.03 කි. ඔබ එය සැබවින්ම ගැටළු සහගත යැයි සලකනවාද?
ඇලෙක්සැන්ඩර්

4
ආරම්භක වේලාව වැදගත් වන්නේ ඔබ පයිතන් ලූපයක් ලෙස හැඳින්වුවහොත් එය වැදගත් වන්නේ පයිතන් වල ලූපය කිරීම ගැන සලකා බලන්න . එවිට ඔබට ආරම්භක පිරිවැය එක් වරක් පමණි. මට නම්, ආරම්භක පිරිවැයෙන් අඩක් මුළු ස්නිපිට් කාලයෙන් අඩකට වඩා වැඩිය, මම සැලකිය යුතු පොදු කාර්යයක් ලෙස සලකමි. (නැවතත්, ලිපිගොනු කුඩා සංඛ්‍යාවක් පමණක් කරන්නේ නම් අදාළ නොවේ)
කෙවින් කොක්ස්

2
echo ""වඩා ශක්තිමත් බව පෙනේ echo -n '\n'. නැතහොත් ඔබට භාවිතා කළ හැකියprintf '\n'
කීත් තොම්සන්

2
මෙය මට හොඳින් ක්‍රියාත්මක විය
ඩැනියෙල් ගෝමස් රිකෝ

13

නොපැමිණෙන, අවසාන නව රේඛාවක් a ට එකතු කිරීම සඳහා සරල, අතේ ගෙන යා හැකි, පොසික්ස් අනුකූල ක්‍රමයක් පෙළ ගොනුවක් වනු ඇත:

[ -n "$(tail -c1 file)" ] && echo >> file

මෙම ප්රවේශය සම්පූර්ණ ගොනුව කියවීමට අවශ්ය නොවේ; එය හුදෙක් EOF වෙත ගොස් එහි සිට වැඩ කළ හැකිය.

මෙම ප්‍රවේශය මඟින් ඔබේ පිටුපස තාවකාලික ලිපිගොනු සෑදීම අවශ්‍ය නොවේ (උදා: sed -i), එබැවින් දෘඩ සබැඳි බලපාන්නේ නැත.

echo ගොනුවට නව රේඛාවක් එකතු කරන්නේ විධාන ආදේශනයේ ප්‍රති result ලය හිස් නොවන නූලක් වූ විට පමණි. මෙය සිදුවිය හැක්කේ ගොනුව හිස් නොවන්නේ නම් සහ අවසාන බයිට් නව රේඛාවක් නොවේ නම් පමණි.

ගොනුවේ අවසාන බයිට් එක නව රේඛාවක් නම්, වලිගය එය නැවත ලබා දෙයි, පසුව විධාන ආදේශනය එය ඉවත් කරයි; ප්‍රති result ලය හිස් නූලකි. -N පරීක්ෂණය අසමත් වන අතර දෝංකාරය ක්‍රියාත්මක නොවේ.

ගොනුව හිස් නම්, විධාන ආදේශනයේ ප්‍රති result ලය ද හිස් නූලක් වන අතර නැවත දෝංකාරය ක්‍රියාත්මක නොවේ. මෙය සුදුසු වන්නේ හිස් ගොනුවක් අවලංගු පෙළ ගොනුවක් නොවන නිසාත් එය හිස් රේඛාවක් සහිත හිස් නොවන පෙළ ගොනුවකට සමාන නොවන නිසාත් ය.


2
yashගොනුවේ අවසාන අක්‍ෂරය බහු-බයිට් අක්ෂරයක් නම් (උදාහරණයක් ලෙස යූටීඑෆ් -8 ස්ථාන වල), හෝ පෙදෙසි සී නම් සහ ගොනුවේ අවසාන බයිට් 8 වන බිට් කට්ටලය තිබේ නම් එය ක්‍රියා නොකරයි . වෙනත් ෂෙල් වෙඩි සමඟ (zsh හැර), ගොනුව NUL බයිට් එකකින් අවසන් වුවහොත් එය නව රේඛාවක් එක් නොකරනු ඇත (නමුත් නැවතත්, එයින් අදහස් වන්නේ නව රේඛාවක් එකතු කළ පසුවත් ආදානය පෙළ නොවන බවයි).
ස්ටෙෆාන් චසෙලාස්


1
ෆෝල්ඩරයක සහ උප ෆෝල්ඩරවල ඇති සෑම ගොනුවක් සඳහාම මෙය ක්‍රියාත්මක කළ හැකිද?
Qwerty

8

වේගවත්ම විසඳුම නම්:

[ -n "$(tail -c1 file)" ] && printf '\n' >>file 

  1. ඇත්තෙන්ම වේගවත්.
    මධ්‍යම ප්‍රමාණයේ ගොනුවකට seq 99999999 >fileමෙය මිලි තත්පර ගත වේ.
    වෙනත් විසඳුම් සඳහා බොහෝ කාලයක් ගතවේ:

    [ -n "$(tail -c1 file)" ] && printf '\n' >>file  0.013 sec
    vi -ecwq file                                    2.544 sec
    paste file 1<> file                             31.943 sec
    ed -s file <<< w                             1m  4.422 sec
    sed -i -e '$a\' file                         3m 20.931 sec
  2. අළු, බාෂ්, lksh, mksh, ksh93, attsh සහ zsh වලින් ක්‍රියා කරන නමුත් යෂ් නොවේ.

  3. නව රේඛාවක් එක් කිරීමට අවශ්‍ය නැතිනම් ගොනු කාලරාමුව වෙනස් නොකරයි.
    මෙහි ඉදිරිපත් කර ඇති අනෙකුත් සියලුම විසඳුම් ගොනුවේ කාලරාමුව වෙනස් කරයි.
  4. ඉහත සියලුම විසඳුම් වලංගු POSIX වේ.

ඔබට යෂ් (සහ ඉහත ලැයිස්තුගත කර ඇති අනෙකුත් සියලුම ෂෙල් වෙඩි) සඳහා අතේ ගෙන යා හැකි විසඳුමක් අවශ්‍ය නම්, එය තව ටිකක් සංකීර්ණ විය හැකිය:

f=file
if       [ "$(tail -c1 "$f"; echo x)" != "$(printf '\nx')" ]
then     printf '\n' >>"$f"
fi

6

ගොනුවක අවසාන බයිට් නව රේඛාවක් දැයි පරීක්ෂා කිරීමට වේගවත්ම ක්‍රමය වන්නේ එම අවසාන බයිට් එක පමණක් කියවීමයි. එය කළ හැකිය tail -c1 file. කෙසේ වෙතත්, බයිට් අගය නව රේඛාවක් දැයි පරීක්ෂා කිරීම සඳහා සරලම ක්‍රමය, විධාන ප්‍රසාරණය තුළ සිරස් අතට අළුත් රේඛාවක් ඉවත් කිරීම සාමාන්‍යයෙන් යෂ් වලින් අසමත් වේ (නිදසුනක් ලෙස), ගොනුවේ අවසාන අක්‍ෂරය යූටීඑෆ්- 8 අගය.

ගොනුවක අවසාන බයිට් නව රේඛාවක් දැයි සොයා ගැනීමට නිවැරදි, POSIX- අනුකූල, සියලු (සාධාරණ) ෂෙල් වෙඩි ක්‍රමය වන්නේ xxd හෝ hexdump භාවිතා කිරීමයි:

tail -c1 file | xxd -u -p
tail -c1 file | hexdump -v -e '/1 "%02X"'

එවිට, ඉහත ප්‍රතිදානය සංසන්දනය කිරීමෙන් 0Aශක්තිමත් පරීක්ෂණයක් ලබා දෙනු ඇත.
වෙනත් ආකාරයකින් හිස් ගොනුවකට නව පේළියක් එක් කිරීමෙන් වැළකී සිටීම ප්‍රයෝජනවත් වේ. ඇත්ත වශයෙන්ම
අවසාන චරිතය සැපයීමට අපොහොසත් වන ගොනුව 0A:

f=file
a=$(tail -c1 "$f" | hexdump -v -e '/1 "%02X"')
[ -s "$f" -a "$a" != "0A" ] && echo >> "$f"

කෙටි හා මිහිරි. අන්තිම බයිටය කියවන විට මෙය ඉතා සුළු කාලයක් ගතවේ (EOF වෙත යොමුවන්න). ගොනුව විශාල නම් කමක් නැත. අවශ්‍ය නම් එක් බයිට් එකක් පමණක් එක් කරන්න.

තාවකාලික ලිපිගොනු අවශ්‍ය නොවේ. දෘඩ සබැඳි වලට බලපෑමක් නැත.

මෙම පරීක්ෂණය දෙවරක් ක්රියාත්මක වන්නේ නම්, එය වනු ඇත නොවන තවත් නව පේළියකට යොමු කිරීමේ අක්ෂරය එකතු කරන්න.


1
rcrw එය ප්‍රයෝජනවත් තොරතුරු එකතු කරන බව මම විශ්වාස කරමි.
අයිසැක්

2
POSIX උපයෝගිතා xxdහෝ නොවන බව සලකන්න hexdump. POSIX මෙවලම් කට්ටලයේ, od -An -tx1බයිට් එකක හෙක්ස් අගය ලබා ගත යුතුය.
ස්ටෙෆාන් චසෙලාස්

@ ස්ටෙෆාන් චැසෙලාස් කරුණාකර එය පිළිතුරක් ලෙස පළ කරන්න; මම මෙහි බොහෝ වාරයක් මෙම අදහස සොයමින් සිටිමි :)
kelvin


POSIX විසින් LF හි අගය 0x0a ලෙස සහතික නොකරන බව සලකන්න. මේ දිනවල අතිශයින්ම දුර්ලභ වුවද පොසික්ස් පද්ධති (ඊබීසීඩීසී පදනම් කරගත්) තවමත් නොමැත.
ස්ටෙෆාන් චසෙලාස්

4

ගොනුව අවසන් වරට සංස්කරණය කළ පරිශීලකයාගේ සංස්කාරකය නිවැරදි කිරීම වඩා හොඳය. ගොනුව සංස්කරණය කළ අවසන් පුද්ගලයා ඔබ නම් - ඔබ භාවිතා කරන්නේ කුමන සංස්කාරකයද, මම අනුමාන කරන්නේ පෙළපොත් ..?


2
Vim යනු ප්‍රශ්නාර්ථයේ සංස්කාරකයයි. නමුත් පොදුවේ ගත් කල, ඔබ හරි, මම රෝග ලක්ෂණ පමණක් නිවැරදි කළ යුතු නොවේ;)
k0pernikus

6
Vim සඳහා, ඔබ ඔබේ මාර්ගයෙන් පිටතට ගොස් ගොනුවේ අවසානයේ නව පේළියක් එක් නොකිරීමට vim ලබා ගැනීම සඳහා ද්විමය-ගොනු-සුරැකීමේ නැටුම කළ යුතුය - එම නර්තනය පමණක් නොකරන්න. නැතහොත්, පවතින ලිපිගොනු නිවැරදිව නිවැරදි කිරීම සඳහා ඒවා විවෘතව තබා ගොනුව සුරකින අතර vim මඟින් ඔබ සඳහා නැතිවූ නව රේඛාව 'නිවැරදි කරනු ඇත' (බහු ලිපිගොනු සඳහා පහසුවෙන් තිර රචනය කළ හැකිය)
AD7six

3
මගේ emacsගොනුව අවසානයේ නව රේඛාවක් එක් නොකරන්න.
enzotib

2
@ AD7six අදහස් දැක්වීමට ස්තූතියි, මම දේවල් කරන විට, මුල් ගොනුවේ අවසානයේ නව රේඛාවක් නොතිබෙන්නේ කෙසේද යන්න පිළිබඳව මම විවිධාකාරයෙන් ෆැන්ටම් වාර්තා ලබා ගනිමි. මම vim සමඟ ගොනුවක් සංස්කරණය කළත් මට එහි නව රේඛාවක් නොතැබිය හැකිය. ඒ නිසා එය හුදෙක් විම්.
ස්ටීවන් ලූ

1
zenzotib: (setq require-final-newline 'ask)මගේ.emacs
කීත් තොම්සන්

4

සමහර නල මාර්ග සැකසීමේදී ඔබට ඉක්මනින් නව රේඛාවක් එක් කිරීමට අවශ්‍ය නම්, මෙය භාවිතා කරන්න:

outputting_program | { cat ; echo ; }

එය ද POSIX අනුකූල වේ.

ඇත්ත වශයෙන්ම, ඔබට එය ගොනුවකට හරවා යැවිය හැකිය.


2
මට මෙය නල මාර්ගයක භාවිතා කළ හැකිය යන කාරණය ප්‍රයෝජනවත් වේ. CSV ගොනුවක ඇති ශීර්ෂකය හැර පේළි ගණන ගණනය කිරීමට මෙය මට ඉඩ දෙයි. නව රේඛාවක් හෝ ප්‍රවාහනයකින් අවසන් නොවන වින්ඩෝස් ලිපිගොනු වල නිවැරදි රේඛා සංඛ්‍යාවක් ලබා ගැනීමට එය උපකාරී වේ. cat file.csv | tr "\r" "\n" | { cat; echo; } | sed "/^[[:space:]]*$/d" | tail -n +2 | wc -l
කයිල් ටොලේ

3

ආදානයේ කිසිදු ශුන්‍යතාවයක් නොමැති බව සපයා ඇත:

paste - <>infile >&0

... සෑම විටම නව රේඛාවක් අනන්තයෙහි වලිගය කෙළවරට එකතු කිරීමට පමණක් ප්‍රමාණවත් වේ. එය නිවැරදිව ලබා ගැනීම සඳහා එක් වරක් පමණක් ආදාන ගොනුව කියවිය යුතුය.


Stdin සහ stdout එකම විවෘත ගොනු විස්තරයක් බෙදා ගන්නා බැවින් එය එසේ ක්‍රියා නොකරනු ඇත (එබැවින් ගොනුව තුළ කර්සරය). ඒ paste infile 1<> infileවෙනුවට ඔබට අවශ්‍යයි .
ස්ටෙෆාන් චසෙලාස්

2

එය ප්‍රශ්නයට කෙලින්ම පිළිතුරු නොදුන්නද, නව රේඛාවෙන් අවසන් නොවන ලිපිගොනු සොයා ගැනීමට මා ලියූ අදාළ පිටපතක් මෙන්න. එය ඉතා වේගවත් ය.

find . -type f | # sort |        # sort file names if you like
/usr/bin/perl -lne '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

පර්ල් ස්ක්‍රිප්ට් එක stdin වෙතින් (විකල්ප වශයෙන් වර්ග කර ඇති) ගොනු නාම ලැයිස්තුවක් කියවන අතර සෑම ගොනුවක් සඳහාම ගොනුව නව රේඛාවකින් අවසන් වේද නැද්ද යන්න තීරණය කිරීම සඳහා අවසාන බයිට් එක කියවයි. එය ඉතා වේගවත් බැවින් එය එක් එක් ගොනුවේ සම්පූර්ණ අන්තර්ගතය කියවීමෙන් වළක්වයි. එය කියවන සෑම ගොනුවක් සඳහාම එක් පේළියක් ප්‍රතිදානය කරයි, යම් දෝෂයක් සිදුවුවහොත් "හිස්:" ගොනුව හිස් නම් (නව රේඛාවෙන් අවසන් නොවේ!), "ඊඕඑල්:" ("අවසානය පේළිය ") ගොනුව නව රේඛාවකින් අවසන් වන්නේ නම් සහ" ඊඕඑල් නැත: "ගොනුව නව රේඛාවකින් අවසන් නොවන්නේ නම්.

සටහන: ස්ක්‍රිප්ටයේ නව රේඛා අඩංගු ගොනු නම් හසුරුවන්නේ නැත. ඔබ GNU හෝ BSD පද්ධතියක සිටී නම්, සොයා ගැනීමට -print0, -z වර්ග කිරීමට සහ -0 perl වෙත එකතු කිරීමෙන් ඔබට හැකි සියලුම ගොනු නම් හැසිරවිය හැකිය:

find . -type f -print0 | sort -z |
/usr/bin/perl -ln0e '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

ඇත්ත වශයෙන්ම, ඔබට තවමත් නිමැවුම් වල නව රේඛා සමඟ ගොනු නාම කේතනය කිරීමේ ක්‍රමයක් ඉදිරිපත් කළ යුතුව ඇත (පා er කයාට අභ්‍යාසයක් ලෙස ඉතිරිව ඇත).

අවශ්‍ය නම්, එකක් නොමැති ගොනු වලට නව රේඛාවක් එකතු කිරීම සඳහා ප්‍රතිදානය පෙරීම කළ හැකිය

 echo >> "$filename"

අවසාන නව රේඛාවක් නොමැතිකම ස්ක්‍රිප්ට් වල දෝෂ ඇති විය හැකි බැවින් සමහර ගොනුවල අනුවාදයන් සහ වෙනත් උපයෝගිතා එවැනි ගොනුවක් කියවීමේදී නැතිවූ අවසාන නව රේඛාවක් නිසියාකාරව හසුරුවන්නේ නැත.

මගේ අත්දැකීම් අනුව, අවසාන නව රේඛාවක් නොමැතිකම සිදුවන්නේ ලිපිගොනු සංස්කරණය කිරීම සඳහා විවිධ වින්ඩෝස් උපයෝගිතා භාවිතා කිරීමෙනි. ගොනුවක් සංස්කරණය කිරීමේදී අවසාන නව රේඛාවක් අස්ථානගත වී ඇති බව මා දැක නැත, එය එවැනි ලිපිගොනු පිළිබඳ වාර්තා කරනු ඇත.

අවසාන වශයෙන්, නව රේඛාවෙන් අවසන් නොවන ලිපිගොනු මුද්‍රණය කිරීම සඳහා ඒවායේ ගොනු නාම යෙදවුම් හරහා ලූප කළ හැකි කෙටි (නමුත් මන්දගාමී) ස්ක්‍රිප්ට් තිබේ:

/usr/bin/perl -ne 'print "$ARGV\n" if /.\z/' -- FILE1 FILE2 ...

1

මෙම vi/ vim/ exසංස්කාරකවරුන් ස්වයංක්රීයව එකතු කරන්න <EOL>EOF දී ගොනුව දැනටමත් එය නොමැති නම් මිස,.

එබැවින් උත්සාහ කරන්න:

vi -ecwq foo.txt

එය සමාන වේ:

ex -cwq foo.txt

පරීක්ෂා කිරීම:

$ printf foo > foo.txt && wc foo.txt
0 1 3 foo.txt
$ ex -scwq foo.txt && wc foo.txt
1 1 4 foo.txt

බහුවිධ ලිපිගොනු නිවැරදි කිරීම සඳහා, පරීක්ෂා කරන්න: බොහෝ ගොනු සඳහා 'ගොනුව අවසානයේ නව රේඛාවක් නැත' යන්න නිවැරදි කරන්නේ කෙසේද? SO හි

මෙය එතරම් වැදගත් වන්නේ ඇයි? අපගේ ලිපිගොනු POSIX අනුකූලව තබා ගැනීමට .


0

වත්මන් නාමාවලියෙහි ඇති සියලුම ලිපිගොනු වලට පිළිගත් පිළිතුර යෙදීම සඳහා (ඊට අමතරව උප බහලුම්):

$ find . -type f -exec sed -i -e '$a\' {} \;

මෙය ලිනක්ස් (උබුන්ටු) මත ක්‍රියා කරයි. OS X හි ඔබට බොහෝ විට භාවිතා කිරීමට සිදුවනු ඇත -i ''(පරීක්ෂා නොකළ).


4
find .ඇතුලත ගොනු ඇතුළුව සියලුම ගොනු ලැයිස්තුගත කරන බව සලකන්න .git. බැහැර කිරීම සඳහා:find . -type f -not -path './.git/*' -exec sed -i -e '$a\' {} \;
friederbluemle

මම එය ක්‍රියාත්මක කිරීමට පෙර මෙම අදහස කියවා / ඒ ගැන සිතුවා නම් හොඳයි. හා හොඳයි.
kstev

0

අවම වශයෙන් GNU අනුවාද වල, එහි ආදානය සරලව grep ''හෝawk 1 කැනොනිකල් කර, දැනටමත් නොමැති නම් අවසාන නව රේඛාවක් එක් කරයි. ඔවුන් ක්‍රියාවලිය තුළ ගොනුව පිටපත් කරයි, එය විශාල නම් කාලය ගත වේ (නමුත් ප්‍රභවය කෙසේ හෝ කියවීමට තරම් විශාල නොවිය යුතුද?) සහ ඔබ වැනි දෙයක් නොකරන්නේ නම් මෝඩමය යාවත්කාලීන කරයි

 mv file old; grep '' <old >file; touch -r old file

.


නැතහොත් grep '' file 1<> file, එය තවමත් ගොනුව සම්පූර්ණයෙන් කියවා ලිවිය හැකිය.
ස්ටෙෆාන් චසෙලාස්

-1

මෙය AIX ksh හි ක්‍රියාත්මක වේ:

lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
    echo "/n" >> *filename*
fi

මගේ නඩුවේදී, ගොනුවේ නව රේඛාව අස්ථානගත වී ඇත්නම්, wcවිධානය මඟින් වටිනාකමක් ලබා දෙන 2අතර අපි නව රේඛාවක් ලියන්නෙමු.


ප්‍රතිපෝෂණය ඉහළ හෝ පහත් ස්වරූපයෙන් පැමිණෙනු ඇත, නැතහොත් ඔබේ පිළිතුරු / ප්‍රශ්න තව දුරටත් ගෙනහැර දැක්වීමට අදහස් විමසනු ඇත. එය කාරණය දක්වා තබා ගන්න, stackexchange වෙත සාදරයෙන් පිළිගනිමු!
k0pernikus

-1

පැට්‍රික් ඔස්සිටිගේ පිළිතුරට එකතු කරමින් , ඔබට එය විශේෂිත නාමාවලියකට යෙදවීමට අවශ්‍ය නම්, ඔබට මෙයද භාවිතා කළ හැකිය:

find -type f | while read f; do tail -n1 $f | read -r _ || echo >> $f; done

ඔබ නව රේඛා එක් කිරීමට කැමති නාමාවලිය තුළ මෙය ක්‍රියාත්මක කරන්න.


-1

echo $'' >> <FILE_NAME> ගොනුවේ අවසානයට හිස් පේළියක් එක් කරයි.

echo $'\n\n' >> <FILE_NAME> ගොනුවේ අවසානයට හිස් පේළි 3 ක් එකතු කරයි.


StackExchange හි විහිලු හැඩතල ගැන්වීමක් ඇත, මම එය ඔබ වෙනුවෙන් සවි කළෙමි :-)
පීටර් - මොනිකා නැවත ස්ථාපනය කරන්න

-1

ඔබේ ගොනුව වින්ඩෝස් රේඛා අවසානය සමඟ අවසන් \r\nකර ඔබ ලිනක්ස් හි සිටී නම් ඔබට මෙම sedවිධානය භාවිතා කළ හැකිය . එය \r\nඅවසන් පේළියට එකතු කරන්නේ එය දැනටමත් නොමැති නම් පමණි:

sed -i -e '$s/\([^\r]\)$/\1\r\n/'

පැහැදිලි කිරීම:

-i    replace in place
-e    script to run
$     matches last line of a file
s     substitute
\([^\r]\)$    search the last character in the line which is not a \r
\1\r\n    replace it with itself and add \r\n

අවසාන පේළියේ දැනටමත් a අඩංගු \r\nනම් සෙවුම් regexp නොගැලපේ, එබැවින් කිසිවක් සිදු නොවේ.


-1

ඔබට පිටපතක් ලිවිය හැකිය fix-non-delimited-line:

#! /bin/zsh -
zmodload zsh/system || exit
ret=0
for file do
  if sysopen -rwu0 -- "$file"; then
    if sysseek -w end -1; then
      read -r x || print -u0
    else
      syserror -p "Can't seek in $file before the last byte: "
      ret=1
    fi
  else
    ret=1
  fi
done
exit $ret

මෙහි දී ඇති සමහර විසඳුම් වලට පටහැනිව, එය

  • එය කිසිදු ක්‍රියාවලියක් සඳහා නොයෙදෙන, සෑම ගොනුවක් සඳහාම එක් බයිට් එකක් පමණක් කියවන අතර ගොනුව නැවත ලිවීම නොකිරීමට කාර්යක්ෂම විය යුතුය (නව රේඛාවක් එකතු කරයි)
  • සිම්ලින්ක් / දෘඩ සබැඳි බිඳ නොදමනු ඇත හෝ පාර-දත්ත වලට බලපාන්නේ නැත (එසේම, ctime / mtime යාවත්කාලීන වන්නේ නව රේඛාවක් එකතු කළ විට පමණි)
  • අන්තිම බයිට් NUL හෝ බහු-බයිට් අක්ෂරයක කොටසක් වුවද හරි ක්‍රියා කළ යුතුය.
  • ලිපිගොනු නාමවල අඩංගු විය හැකි අක්ෂර හෝ අක්‍ෂර නොසලකා හරි ක්‍රියා කළ යුතුය
  • නිවැරදිව කියවිය නොහැකි හෝ ලිවිය නොහැකි හෝ නොපෙනෙන ලිපිගොනු හැසිරවිය යුතුය (සහ ඒ අනුව දෝෂ වාර්තා කරන්න)
  • හිස් ලිපිගොනු සඳහා නව රේඛාවක් එක් නොකළ යුතුය (නමුත් එම අවස්ථාවේදී අවලංගු සෙවීමක් පිළිබඳ දෝෂයක් වාර්තා කරයි)

උදාහරණයක් ලෙස ඔබට එය භාවිතා කළ හැකිය:

that-script *.txt

හෝ:

git ls-files -z | xargs -0 that-script

POSIXly, ඔබට සමාන ක්‍රියාකාරී යමක් කළ හැකිය

export LC_ALL=C
ret=0
for file do
  [ -s "$file" ] || continue
  {
    c=$(tail -c 1 | od -An -vtc)
    case $c in
      (*'\n'*) ;;
      (*[![:space:]]*) printf '\n' >&0 || ret=$?;;
      (*) ret=1;; # tail likely failed
    esac
  } 0<> "$file" || ret=$? # record failure to open
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.